2023 电商网站系统设计的原则
1、高并发原则
1.1 Restful API ,满足幂等,无状态。
1.2 系统渐进式演进。
创业公司或公司开展新业务时,业务需要短时间内开展,此时需要一个最小可行产品来支持业务。即解决当下最紧急的问题即可。然后,再做针对未来的架构规划。
1.3 电商系统的读原高于写。不同行业可能有 1/100甚至 1/1000 以上的读写比例。即使同一家电商,不同运营活动可能也有不同的读写比例。
从“读写维度”拆分系统。
1.4 满足系统高并发就需要“拆分”负载。洪水来时多打通几条泄洪渠。
拆分的几个维度:
系统维度:按照系统功能即业务拆分,比如商品,购物车,订单,支付等。
功能维度:对业务再拆,比如订单拆为现金订单,月结订单;优惠券拆为创建券,领券,用券系统等。
读写维度:由于电商系统一般是读远大于写,故读的部分拆分:商品详情读/写,读服务使用缓存以提升性能。还有订单读/写,购物车读/写,优惠券读/写,货架楼层读/写,品牌读/写等。读商品详情页时,需要读取多种数据源聚合返回给前端。此场景下,还可以提前把商品详情页静态化,甚至详情页中的动态数据如库存,价格可以聚合到一个数据源中(数据异构拆分系统),以提升系统的性能和可靠性。当写负载大时,考虑读写分离,写缓存,写队列;读缓存,甚至分库分表。
AOP 维度:根据访问特征,按照 AOP 进行拆分,如商品详情页分为 CDN,页面渲染系统。商品详情页部署静态化页面到 CDN,少量的动态数据再动态请求。
还有一个拆分是从软件开发者角度,模块维度:如三层架构 web,service,DAO。
1.5 服务化
进程内服务->单击远程服务->集群手动注册服务->自动注册服务和发现服务->服务的分组、隔离、路由->服务治理如限流,降级,黑白名单。
单点系统(进程内整套服务)-->横向扩展(Nginx 负载均衡,单点变多点,多个进程内整套服务),DB 读写分离。再迭代升级服务化。
1.6 消息队列
消息队列解耦一些不需要同步调用的服务或者订阅(自己系统关心的数据变化)。
一对多:一个数据生产者对应多个数据消费者。
异步处理:比如支付系统。第三方异步服务。
流量削峰、缓冲。
生产消息失败时需要善后。消息重复接收又需要业务层面防重。比如一个订单只能支付成功一次。一个订单内一种 SKU只能减一次库存。
比如:支付是否成功,需要后期再校对。
大流量场景下,一般都是牺牲强一致性,而保证最终一致性。
比如,扣减库存:
1 redis 扣减库存 ---2-->记录扣减日志
↑3
同步 worker --4-->DB
直接在 redis 中扣减,记录扣减日志,worker 同步到 DB。
比如,交易订单:
↓6
→1 订单生成服务→2.1 支付服务→3.1 订单 redis ←7.2----订单状态机 →↓
↓2.2 订单队列←4------同步 worker-----→5→订单中心表 ←7.1
生成订单服务调用支付服务,将订单存到订单 redis 和订单队列表。同步 worker 同步订单到订单中心表。支付是异步服务,结果异步更新到订单 redis 和订单中心表。若订单中心表还没有此订单,则可以重试或放弃以等待下一次定期更新。
如果用户查看单个订单详情,则直接从订单 redis 中查,如果查不到,还需要读 DB。如果查询用户订单列表,则合并 订单redis(最新状态) 和订单列表,如果差不多还需要查 DB。
同步 worker 设计:并发处理和重复处理。
订单列表的新增字段:审核人,审核状态,审核时间等。
1.7 数据异构
一般情况,如果查询商品详情,需要关联多个表。商品表,运营活动表,库存表,价格表,厂家表,注册证表等。不能从一个数据库表返回,可读性能较低。如果能把一个商品的这些数据按商品 ID 抽出到一个库表,则会提升可读性。甚至可以这些异构数据存到 mangodb一张表内或缓存到 redis 内。
数据异构:是通过 MQ 机制接收数据变更,然后原子化存储到合适的存储引擎如 redis 或持久化存储
数据聚合:可选。数据异构目的是把数据从多个数据源拿来。数据聚合是聚合到一起方便前端一次调用即可拿到所有数据。
1.8 缓存
CDN 缓存静态化页面,或半静态化页面(含动态加载数据)。尤其对于大量读页面,URL 静态化设计,降低穿透 CDN回源到源服务器的请求,提高性能。CDN 缓存适合爬虫。
Nginx 接入层缓存:
一致性哈希 URL,给商品详情页做负载均衡,即一个商品详情页总是请求某个或几个服务器。即分流分片。
local redis cache,在 Nginx 上部署本地 redis缓存。或从Nginx 直接访问缓存服务器。缓存服务器可以做成 reload 反序列化从而不丢失缓存数据。
应用层缓存:
在应用服务器上部署 redis,本组内多个应用服务器之间采用主从机制同步数据。
1.9 分布式缓存
当单台 redis 缓存不了需要缓存的数据量,可以分流或直接分布式缓存。分布式缓存也需要一致性哈希,把不同的数据按一定的规则分区,分散到不同的缓存主机上。以应对超大量缓存数据的场景。
1.10 并发获取数据
一个读服务内可细分多个读操作时,仔细分析业务,把可以并行读取的操作并行化。最后聚合一次返回。
2、高可用原则
2.1 降级
2.2 限流
2.3 切流量
2.4 回滚