您的位置:首页 > 运维架构 > 网站架构

[亿级流量架构读后记录一] 交易性系统设计原则

2018-02-28 18:25 651 查看

交易性系统设计原则

高并发原则

1. 无状态

应用无状态, 配置文件有状态, 方便水平扩展

2. 拆分

系统维度— 商品, 购物车, 结算, 订单);

功能维度— 优惠券系统可以拆分为后台券创建系统, 领券系统, 用券系统等;

读写维度— 读服务架构缓存; 写服务分库分表; 聚合读取的数据,如商品详情页, 考虑将分散的数据聚合一处存储;

AOP维度— 根据访问特征, 比如, 商品详情页可以分为CDN, 页面渲染系统; CDN就是一个AOP系统;

模块维度— 比如按照基础或者代码维护特征进行拆分, 如基础模块分库分表, 数据库连接池等基础服务; 代码结构一般按照三层架构 web, service, dao进行拆分;

3. 服务化

​ 除了服务的自动注册和发现, 还要考虑服务的分组/隔离,比如,有的系统访问过大,导致把整个服务打挂,因此,需要为不同的调用方提供不同的服务分组,隔离访问(其实就是进行隔离). 后期随着调用量增加还要考虑服务的限流/黑白名单等. 其中掺杂细节: 超时时间/重试机制/服务路由(能动态切换不同的分组)/故障补偿等.

4. 消息队列

​ 消息队列的重要性不言而喻, 功能: 服务解耦(一对多消费)、异步消费、流量削峰/缓冲等。比如,订单数据, 有非常多的系统关心并订阅,比如,订单生产系统、定期送系统、订单风控系统等。如果订阅者太多,那么订阅单个消息队列就会成为瓶颈,此时需要考虑对消息队列进行多个镜像复制。

​ 当然还有生产消息失败,消息重复接受时的场景。指定重试次数内进行生产重试(或者记录,报警)。对于消息重复问题,需要做防重处理。

案例:

扣减库存,redis扣减库存 > 记录扣减日志 (后台同步 worker 将其 同步到 DB);

交易订单系统 , 从购物车确认结算时, 将订单存储到订单redis和订单队列表(可按需水平拓展多个表), 然后通过同步worker同步到订单中心表; 假设用户支付订单, 订单状态机会驱动状态变更,此时,可能订单队列表的订单还没有同步到订单中心表(不存在或者数据不对),状态机要根据实际情况进行重试。

​ 如果用户查看单个订单详情, 那么可以直接从订单redis中查到。但如果查询订单列表,则考虑订单redis和列表的合并。

​ 同步worker在设计时, 需要考虑并发处理和重复处理的问题。比如,使用单机串行扫描处理(每台worker扫描其中的一部分表)还是集群处理(Map-Reduce)。另外,需要考虑是否需要对订单队列表添加相关字段: 处理人(哪个应用正在处理)和处理状态(正在处理、已处理、处理失败)、最后处理时间(应对超时)、失败次数等。

​ 数据校对: 在消息异步机制场景下,可能存在消息丢失,需要考虑进行数据校对和修正来保证数据的一致性和完整性.可通过worker定期去扫描原始表, 通过对业务数据进行比对, 有问题进行补偿, 扫描周期按需定义.

5. 数据异构

数据异构: 订单分库分表按照订单Id进行分,如果要查询某个用户的订单列表,则需要聚合多个表的数据后才能返回,这样会导致订单表读性能很低.此时需要对订单表进行异构。异构一套用户订单表,按照用户id进行分库分表。另外,还需要考虑对历史订单数据进行归档处理,以提升服务的性能和稳定性。而有些数据异构的意义不大,如库存价格,可以考虑异步加载,或者合并并发请求。

数据闭环: 数据闭环如商品详情页,因为数据来源太多,影响服务稳定性因素太多。因此,最好的办法是把使用到的数据进行异构存储,形成数据闭环,基本步骤如下:

数据异构:通过如MQ机制进行接收数据变更,然后原子化存储到合适的存储引擎,如redis或持久化KV存储。

数据聚合:这步是可选的,数据异构目的是把数据从多个数据源拿过来,数据聚合的目的是把这些数据做个聚合,这样前端一次调用即可,一般存储到KV中。

前端展示:前端通过一次或者少量几次调用拿到所需要的数据。

​ 这种方式的好处就是数据的闭环,任何依赖系统出问题了,还是能正常工作,只是更新会有积压,但是不影响前端展示。

​ 另外,如果一次需要多个数据,可以考虑使用Hash Tag机制将相关数据聚合到一个实例,如在展示商品详情页时需要商品基本信息”p:productId:和商品规格参数”d:productId:”,使用冒号中间的productId作为数据分片key,这样相同productId的商品相关数据就在一个实例。

​ 数据闭环和数据异构其实是一个概念,目的都是事先数据的自我控制,当其他系统出问题时不影响自己的系统,或者自己出问题时不影响其他系统。一般通过消息队列来实现数据分发。

6. 缓存银弹

浏览器端缓存

app客户端缓存

CDN缓存 (需要注意url中不能有随机数,否则穿透CDN回源到源服务器。对于爬虫,可以返回过期数据不回源)

接入层缓存,对于没有CDN缓存的应用来说,考虑使用nginx搭建一层接入层,该接入层考虑如下机制:

url重写:将url按照指定的顺序或格式重写,去除随机数。

一致性哈希

proxy_cache: 使用内存级/SSD级代理缓存来缓存内容。

proxy_cache_lock: 使用lock机制,将多个回源合并为一个,以减少回源量,并设置相应的lock超时时间。 当多个客户端同时请求同一份内容时,如果开启proxy_cache_lock(默认off)则只有一个请求被发送至后端;其他请求将等待该内容返回;当第一个请求返回时,其他请求将从缓存中获取内容返回;当第一个请求超过了proxy_cache_lock_timeout超时时间(默认5s),则其他请求将同时请求到后端来获取响应,且响应不会被缓存;启用proxy_cache_lock可以应对雪崩效应。

shared_dict: 如果架构使用了nginx + lua实现,则可以考虑使用 lua shared_dict进行cache,最大的好处就是reload缓存不会丢失。

​ 此处注意,对于托底(或兜底,指降级后显示的)数据或异常数据,不应该让其缓存,否则用户会很长一段时间看到这些数据。

应用层缓存,tomcat 或者 local redis cache,或者接入层使用shared_dict来讲缓存前置,以减少风暴。

分布式缓存,如果数量不大,使用local redis是最优的。但是数据量太大,单服务器存储不了,可以使用分片机制将流量分散到多台,或者直接用分布式缓存。

架构缓存例子:

首先接入层(nginx + lua)读取本地proxy cache / local cache

如果不命中, 则接入层会接着读取分布式redis缓存

如果还不命中, 则会回源到Tomcat, 然后读取Tomcat应用堆内cache

如果都没有命中, 则调用依赖业务来获取数据, 然后异步化写到redis集群等

​ 此种架构, 因为使用nginx + lua, 第二三步可使用lua-resty-lock非阻塞锁减少峰值时需要的回源量; 如果你的服务是用户维度的,那么这种非阻塞锁大部分情况下不会有太大的作用

7. 并发化 所谓 fork/join

高可用原则

1. 降级

​ 对于一个高可用服务,很重要的一个设计就是降级开关,在设计降级开关时,主要依据如下思路.

开关集中化管理: 通过推送机制把开关推送到各个应用.

可降级的多级读服务: 比如服务调用降级为只读本地缓存、只读分布式缓存、只读默认降级数据(如库存状态默认有货, 即默认值).

开关前置化: 如架构是nginx->tomcat, 可以将开关前置到nginx接入层,在nginx层做开关,请求流量回源后端应用或者只是一部分流量回源.

业务降级: 即高峰时, 保证核心业务,保障数据最终一致性即可. 这样可以把一些同步调用改成异步滴啊用, 优先处理高优先级数据或特殊特征的数据, 合理分配进入系统的流量, 以保障系统可用.

2. 限流

​ 限流的目的是防止恶意请求流量, 恶意攻击, 或防止流量超出系统峰值. 可考虑一下思路:

恶意请求流量只访问到cache.

对于穿透到后端应用的流量可以考虑使用nginx的limit的模块处理.

对于恶意ip可以使用nginx deny进行屏蔽.

原则是限制流量传统到后端薄弱的应用层.

3. 切流量

​ DNS、HttpDns、lVS/HaProxy、nginx 做切换

4. 可回滚

​ 事务回滚、代码回滚、部署版本回滚、数据版本回滚、静态资源回滚就

业务涉及原则

1. 防重设计

比如, 购物侧结算页需要考虑重复提交

下单扣库存时需要防止重复扣减库存, 解决方案可考虑防重key, 防重表.

重复支付, 渠道不一样是无法防止重复支付的. 但是, 在系统设计的时候, 需要将支付的每笔情况记录下来.

2. 幂等设计

​ 比如消息重复, 第三方异步回调等

3. 流程可定义

​ 保险, 承保流程和理赔流程是分离的, 在需要时进行关联, 从而复用, 并能提供个性化理赔.

4. 状态与状态机

​ 一般会存在正向状态(待退款, 待发货, 已发货, 完成)和逆向状态(取消, 退款)等. 正向状态和逆向状态应该根据系统的特征来决定要不要分离存储. 状态设计时应有状态轨迹, 方便用户跟踪当前订单的轨迹并记录相关日志, 万一出问题时可回溯问题.

​ 如果状态很多时,可以考虑使用状态机驱动状态的变更和后续流程节点操作, 能更好控制状态迁移; 还要考虑并发状态修改问题, 如一个订单同时只能有一个修改; 状态变更的有序问题, 以及状态变更消息的先到后到问题, 如支付成功消息和用户取消消息的时间差.

5. 后台系统操作可反馈

6. 后台系统审批化

7. 文档和注释

8. 备份 (包括代码和人员)

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  高性能 系统设计