问题:电商系统的主要难点在哪里?
电商系统特点:
- 业务庞大,子系统多。
- 并发大,需要容灾。
- CA要求高,也需要一定的P,三者无法兼得。
- 一致性(Consistency)
- 可用性(Availability)
- 分区容错性(Partition tolerance)
关键考虑点:
- 存储分级策略
- 缓冲策略
- 最终一致性
- 应急策略
问题:如何合理减库存?
误点:
- 每次减存操作都进行写DB
- 每次读取库存都进行读DB
- 对DB进行高频次的单条数据操作
关键点:
- 服务是无状态的
- 数据操作要批量写入
- 保持最终一致性
核心思路:
- 利用内存(redis数据库)对读写操作进行缓存,记录库存变更记录。
- 使用一个进程或线程不断将库存变更记录批量持久化到DB。
问题:如何应付秒杀场景?
秒杀场景特点:
- 瞬时流量大(但不持久)
- 读多写少
- 实时性要求高(并行量大)
要解决的问题:
- 减少DB的命中
- 缓存:CDN、OSS、Redis
- 缓冲:MQ、Kafka
- 需要反欺诈(作弊工具)
- 布隆过滤器
- 硬件资源不足时,需要削峰
- 限流
- 降级
- 缓冲(MQ消息队列)
- 缓存一致性实现
- 乐观锁(Redis:指令Watch+exec实现)
关键点:
- 缓存数据(静态与动态数据需区分缓存)
- 恶意请求过滤
- 大量请求时进行降级、限流、缓冲
核心思路:
- 读请求
- 读取秒杀商品静态资源信息(文字、图片等)的请求,直接通过CDN返回回去。
- 读取秒杀商品动态资源信息(库存等)的请求,通过redis读取返回回去。
- 写请求
- 使用布隆过滤器之类的过滤器对请求进行反欺诈请求过滤。
- 如果硬件资源不足,可增加限流、缓冲等对请求再次过滤。
- 对库存进行预扣减(采用乐观锁),库存保留一段时间,过时释放。
- 库存预扣减完成后,可以在前端先关闭请求入口,等待一部分库存释放后再打开入口。
问题:下单、支付的状态变化
要解决的问题:
- 订单表通常很大
- 可通过水平拆分与垂直拆分进行处理
- 订单表需要支持的业务非常多
- 订单状态变化(状态机)需要的资源较多
- 订单表访问非常频繁
- 需要通知的业务方很多(用户、商家、物流等)
关键点:
- 缓冲
- 缓存设计
- 最终一致性
核心思路:
- 使用双写机制,下单将订单写redis进行缓存与写消息队列进行持续持久化到DB
- 订单状态机进行独立处理订单的状态变化。
- 如果用户读取订单数据可能DB中还未完成同步,需要结合redis与DB的数据返回。
问题:如何解决CAP的P(分区容错)问题:
- 多活:多个服务中心
- 两地三中心
- 生产中心
- 同城容灾中心
- 异地灾备中心
- 两地三中心
- 单元化:能提供完整一套服务的所有程序与设备称为一个单元。
- 每个机房有多套单元
- 通过网关与只能DNS进行分流到最近(延迟最低)的单元
- 单元挂了的话,就会通过分布式共识使用另一个单元进行服务
工具的使用建议:
- 消息队列
- 会减低系统的可用性
- 领域解耦但是增加系统的复杂度
- 需要思考幂等性,消息队列是需要消费者确认后,消息才会消失,不然会出现重复发送。
- 保证可靠性,但是吞吐量会降低
- 消息会乱序
- 缓存
- 端缓存:浏览器、APP的缓存
- 代理缓存:中间节点的代理缓存
- CDN:内容分发网络,静态资源必须采用CDN缓存
- 分布式缓存:redis等
- 数据库同步
- Canal的DB同步方案
灾备的处理方案
- 服务降级
- 限流
- 切流量