读书笔记-《一个高并发项目到落地的心酸路 》
一个高并发项目开发到落地的心酸路
首先,我们没有去设计表,没有去设计接口,而是先去测试
测试:
Mysql: 单节点 MySQL 测试它的读和取性能,新建一张 user 表,向里面并发插入数据和查询数据,得到的 TPS 大概在 5k,QPS 大概在 1.2W。
Redis: get 指令 QPS 达到了惊人的 10w,set 指令 TPS 也有 8W,意料之中也惊喜了下,仿佛看到了曙光。
但是,Redis 容易丢失数据,需要考虑高可用方案。
实现方案:
Redis + RocketMQ + MySQL:Redis 满足要求,数据全从 Redis 取,持久化交给 MySQL,写库的时候先发消息,再异步写入数据库
考虑中间节点挂了怎么办:
MySQL不用管,RocketMQ使用同步落盘(见原文)
关键是Redis,不管哪种模式,Redis在高并发下挂掉,都会存在丢失数据的风险。
讨论过后,决定开启 Redis 事务
保存接口的流程就变成了以下步骤:
1. Redis 开启事务,更新 Redis 数据
2. RocketMQ 同步落盘
3. Redis 提交事务
4. MySQL 异步入库
可能存在问题:
第2步,如果 RocketMQ 落盘报错,那么就会有两种情况:
情况一,落盘失败,消息发送失败,好像没什么影响,直接报错就可。
情况二,如果 RocketMQ 发送消息成功,但提示发送失败(无论什么原因),这时候将导致 MySQL和 Redis 数据的最终不一致(MySQL是更新的数据,但是Redis因为MQ这边返回失败,是保持的旧的数据)。
需要Mysql放弃更新的数据
如何处理?
如果考生继续操作,那么mysql的数据会被更新也就没有问题,如果考生不继续操作,那么这条错误的数据必定无法被更新正确
考虑到这个问题,Redis消息加上时间戳,然后每30分钟,比较redis和mysql的时间戳:
- redis时间比较大,说明还没写入mysql
- 正常流程下,如果MQ返回失败,redis事务机制也就失败,失败也就不会有redis时间比较大的这条记录
- 如果MQ返回成功,但是MYSQL写入失败,这种情况下,需要人工介入,将MQ的记录同步到MYSQL
- redis时间比较小
- 说明MQ成功发送给mysql,但是返回给redis的是失败,MySql需要回退
第一轮压测
TPS 4K
问题 IO上面
方案 使用gzip压缩后再存放到redis
第二轮压测
TPS 8k
问题 MQ磁盘带宽 网络IO带宽
方案 分区
第三轮压测
后面就持续优化,详见原文
核心还是最开始的 选用redis 这个方向没错
本文来自博客园,作者:LiYanbin,转载请注明原文链接:https://www.cnblogs.com/stellar-liyanbin/p/18080223