后端系统实例是理解服务端架构最直观的素材。不同于纯理论,一个具体的系统实例能展示模块如何拆分、请求怎样流转、数据在哪落盘。下面整理的十个后端系统实例,都来自常见互联网业务,具备可参考和可简化的特点。

一、电商订单系统
电商订单系统是最经典的后端实例。它核心要解决三个问题:下单扣减库存、订单状态机流转、重复提交幂等。通常我们会将订单服务与库存服务拆开,通过消息队列异步同步,降低耦合。
在接口设计上,创建订单必须携带唯一业务号,比如用户ID加购物车快照哈希。服务端用唯一索引或分布式锁保证不会重复创建。下面是一个简化的订单创建伪代码:
public Order createOrder(String userId, List<Item> items, String bizNo) {
// 先查幂等表,避免重复下单
if (idempotentDao.exist(bizNo)) {
return orderDao.queryByBizNo(bizNo);
}
// 扣库存,失败则抛异常
for (Item item : items) {
stockService.decrease(item.getSkuId(), item.getCount());
}
Order order = orderDao.insert(userId, items, bizNo);
idempotentDao.save(bizNo, order.getId());
return order;
}
这种结构的优点是逻辑清晰,缺点是在高并发时扣库存会成为瓶颈。实际生产中会引入Redis预扣减,再异步落库,提升吞吐量。
二、短链接生成服务
短链服务面对的是海量读请求和少量写请求。核心算法是把长URL映射成短码,可用发号器加62进制压缩。存储层用KV数据库最合适,因为只需要根据短码查长链。
下面是一个用发号器生成短码的示例,利用数据库自增ID转62进制:
def encode(num):
chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
s = ''
while num > 0:
s = chars[num % 62] + s
num = num // 62
return s
def gen_short_url(long_url):
next_id = id_generator.next()
code = encode(next_id)
kv_store.set(code, long_url)
return 'https://s.ipipp.com/' + code
该实例的难点在于发号器高可用。如果只用单库自增,宕机就停服。可以用雪花算法替代,但短码长度会变。架构上通常前置Nginx做302跳转,后端只负责写和查。
三、消息推送系统
消息推送系统负责把通知发给APP或浏览器。它包含连接管理、消息队列、下发通道三个部分。长连接一般用WebSocket或MQTT维护,服务端记录用户设备对应的连接节点。
推送时先写消息表,再投递到MQ,由各个网关节点消费并推给在线设备。离线消息靠定时任务补偿。代码上可用如下结构描述消费逻辑:
func consumePushMsg(msg *PushTask) {
conn := connectionHub.Get(msg.UserId)
if conn == nil {
offlineStore.Save(msg)
return
}
err := conn.WriteJSON(msg.Payload)
if err != nil {
connectionHub.Remove(msg.UserId)
}
}
这个实例告诉我们,推送系统最怕连接雪崩。当节点重启,大量设备重连会让负载飙升,所以要有平滑重连和限流策略。
四、分布式文件存储
文件存储系统要解决上传、断点续传、多副本容灾。最小可用实例是客户端直传对象存储,服务端只发签名URL。进阶做法是自建存储节点,用一致性哈希分片。
下面是一段生成上传签名URL的Node代码:
function getUploadUrl(key, expire) {
const policy = { key: key, expires: Date.now() + expire };
const token = crypto.createHmac('sha1', secret).update(JSON.stringify(policy)).digest('base64');
return 'https://file.ipipp.com/upload?token=' + token;
}
文件系统的核心指标是可用性和成本。多副本提高可用但费空间,纠删码省空间但恢复慢,选型时要看业务对丢失的容忍度。
五、统一权限中心
权限中心集中管理用户、角色、资源。采用RBAC模型最普遍。它提供鉴权接口,各业务线调用时传用户ID和资源标识,中心返回是否放行。
一个简化的鉴权函数如下:
public boolean checkPermission(long uid, String resource) {
Set<String> roles = roleDao.findRoles(uid);
for (String role : roles) {
if (permDao.hasResource(role, resource)) {
return true;
}
}
return false;
}
权限中心容易变成单点,所以要加本地缓存。当角色变更时通过MQ广播清缓存,保证最终一致。
六、爬虫调度系统
爬虫调度系统包含任务队列、 worker集群、去重布隆过滤器。调度器从队列取URL分发给worker,worker抓取后解析并产出新URL。
去重可用布隆过滤器减少重复抓取:
from pybloom_live import ScalableBloomFilter
seen = ScalableBloomFilter()
def should_crawl(url):
if url in seen:
return False
seen.add(url)
return True
该实例的要点是反爬应对。需要随机UA、代理池和抓取频率控制,否则容易被封。架构上worker无状态,方便扩缩容。
七、日志收集平台
日志平台通常由采集端、消息缓冲、存储检索三部分组成。采集端部署在应用机器,用Filebeat类工具推到Kafka,再由消费程序写入ES。
下面是一段消费Kafka写ES的伪代码:
func consumeLog() {
for msg := range kafkaReader {
var log LogEntry
json.Unmarshal(msg.Value, &log)
esClient.Index("app-log", log)
}
}
日志系统价值在于排障。字段要规范,比如必须有traceId,才能串联一次请求的所有日志。
八、支付清结算系统
支付清结算对接渠道和处理账务。它要求绝对准确,通常采用复式记账。每一笔流水同时记借贷,日终对账拉平。
记账核心代码示意:
public void bookEntry(String orderId, long amount) {
ledgerDao.insert(orderId, "ASSET", amount, "DEBIT");
ledgerDao.insert(orderId, "INCOME", amount, "CREDIT");
}
这类系统不能丢数据,所以所有操作要落库加事务,渠道回调做幂等,对账文件每天校验。
九、社交动态feed流
feed流系统有推模式和拉模式。推模式写时扩散,适合关注少场景;拉模式读时聚合,适合粉丝多的大V。
推模式发动态代码:
def publish_post(user_id, content):
post_id = db.insert_post(user_id, content)
followers = db.get_followers(user_id)
for fid in followers:
redis.lpush('feed:' + fid, post_id)
实际多用推拉结合。热用户走拉,普通用户走推,降低存储压力。
十、实时监控告警
监控系统采集指标、做阈值判断、触发告警。常用时序数据库存指标,Prometheus就是典型。
告警规则配置片段:
rules:
- alert: HighCpu
expr: cpu_usage > 85
for: 2m
labels:
level: warning
监控实例的关键是告警收敛,避免风暴。可按服务聚合,并设静默期。
以上十个后端系统实例覆盖了大部分日常开发场景。理解它们后,你再面对新业务,就能快速套用相似结构,先搭骨架再填细节。
backend_systemsystem_designarchitecture_pattern修改时间:2026-08-06 06:27:38