【高并发项目实战】千万级并发的购物车系统设计与代码详解
前言
📫作者简介:小明java问道之路,专注于研究计算机底层/Java/Liunx 内核,就职于大型金融公司后端高级工程师,擅长交易领域的高安全/可用/并发/性能的架构设计📫
🏆InfoQ 签约博主、CSDN 专家博主/Java 领域优质创作者、阿里云专家/签约博主、华为云专家、51CTO 专家🏆
🔥如果此文还不错的话,还请👍关注、点赞、收藏三连支持👍一下博主~
本文导读
购物车写多读多,大量高并发的写大量高并发的读,可以把主数据存储转为 redis 缓存,基于 redis 做主存储,高性能读写异步的把数据同步到 mysql 持久化。本文主要介绍 redis 在千万级系统中设计架构方案,包括主架构设计、缓存一致性方案、大 value 处理方案和 redis 限流和故障恢复降级方案
一、购物车数据模型分析
购物车中实现的功能:加购物车、查看购物车、编辑购物车 sku、编辑掉商品数据、选中购物车里的多个商品去结算、查看购物车商品总数、删除购物车,分享购物车等等
购物车数据量存储在上亿甚至更高,但是由于写入多读取多更新多删除多,日常流量高的时候偶发慢 sql,当前购物车的实现:同步写 mysql 库+异步写 Redis 缓存,对于购物车来说,如果是在搞一些活动(拼单,满减等非单个商品必须进入购物车下单)的时候——购物车写多读多。购物车可能会出现高并发的写,购物车的写操作同步落库,可能会导致数据库的压力很大。
解决方案,购物车写多读多,大量高并发的写大量高并发的读,可以把主数据存储转为 redis 缓存,基于 redis 做主存储,高性能读写异步的把数据同步到 mysql 持久化。
二、缓存架构主架构图
主架构中包括缓存集群、缓存限流、缓存大 value 处理、HotKey 探测系统、redis 故障恢复降级和 redis-mysql 数据同步
1、缓存一致性方案设计
一、对于所有的 DB 操作都不去添加具体的删除缓存的操作,而是通过 canal 监听 binlog 的方式
二、待数据确认已提交到数据库后,通过监听的变化,解析出对应的数据后,过滤掉非增删改的 binlog
三、然后通过常量类配置的需要处理数据一致性的相关表以及关键字段和缓存前缀 key,进行组装出需要进行删除的缓存 key。并且通过 mq 的 ack 机制来保证缓存一定会被删除掉。
2、缓存限流设计
防止 redis 崩溃之后,系统无法正常运转,所以我们需要做一个降级处理。系统操作 redis 的所有方法一般都是通过 RedisCache 和 Redislock 两个类来处理的,所以我们通过 AOP 切面的方式,对这两个类中的所有方法做一个切面,如果在这里执行 redis 操作的时候,redis 挂掉了,连接失败了,那么方法会抛异常,我们在切面处理方法上,捕捉异常,然后记录一下是 redis 挂掉还是网络暂时的波动
3、大 Value 处理设计方案
一、搭建的 redis 集群
二、在 canal 中已经创建好了监听,存储到 mysql 中 redis_large_key_log 表的 canal instance
三、在每天凌晨 3 点,会将 Redis 中的大 key(value)数据,通过 canal instance 发送到 MQ 四、消费 redis_large_key_log 表的 binlog 数据,该数据包含 Redis 的大 key(value)信息五、将大 value 切分成多个 key,返回时拼接组装
三、复杂缓存与异步落库代码设计
购物车写多读多场景,缓存作为主数据存储,抗高并发写和读,落库异步,商品系统一般来说也会使用缓存架构来提供读的接口的实现。
同时购物车里是需要包含很多数据的,分成多个缓存 key,进行缓存操作。
四、购物车异步落库的消息丢失与不一致
购物车的主数据存储是通过 redis 来实现的,写和读 redis 没有不一致的问题(不崩的情况下)
用 redis 数据存储,万一 redis 集群全盘都崩溃了以后,这个时候就会导致我们的购物车的主数据都没了,mysql 数据库来进行降级, 降级提供购物车的写和读,等缓存恢复了以后,再进行缓存 prewarn 预热的加载,把数据库的数据加载到缓存。
1、mq 系统或 mysql 崩溃
如果要是我们刚刚写完缓存了之后,还没来得及发送消息到 mq 里去,mq 系统崩了,导致缓存写成功了,但是异步消息没过去,mq 出了一些故障,导致消息没发送成功,redis 里有数据, mq 和数据库里面没有消息和数据,导致 redis 和 mysql 数据不一致,只要 redis 中有数据就可以了,因为读写 redis,mysql 只做备份,mysql 需要备份增量
2、redis 崩溃
redis 崩溃,但是 mysql 没有同步到,结果->丢一条数据(临时性存储空间,极端情况,不影响主业务使用)业务上来说,购物车是临时性的数据,仅仅是把一些商品再购物车里进行暂存而已,迟早购买或忘记,要不然会直接去发起购买,这些数据就得删除,时间一长,用户也不清楚加了什么。极端情况下少了商品,需要用户重新添加购物车。
五、写入商品多线程并发问题代码设计
使用 redis 提供的分布式锁:
六、应用新缓存数据结构,购物车的查询功能实践
查询缓存操作:
总结
购物车系统写多读多,大量高并发的写大量高并发的读,可以把主数据存储转为 redis 缓存,基于 redis 做主存储,高性能读写异步的把数据同步到 mysql 持久化。本文主要在 redis 在千万级系统中设计架构方案,包括主架构设计、缓存一致性方案、大 value 处理方案和 redis 限流和故障恢复降级提供方案设计和代码设计
版权声明: 本文为 InfoQ 作者【小明Java问道之路】的原创文章。
原文链接:【http://xie.infoq.cn/article/abb7e08c830d76fe0524eec29】。文章转载请联系作者。
评论