读书笔记-《一个高并发项目到落地的心酸路 》

一个高并发项目开发到落地的心酸路

首先,我们没有去设计表,没有去设计接口,而是先去测试

测试:

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 这个方向没错

posted @ 2024-03-18 13:40  LiYanbin  阅读(3)  评论(0编辑  收藏  举报