本质是行锁争抢导致串行化,须用redis缓存+批量落库实现异步写、逻辑分片变单点为多点并行,并辅以消息队列削峰和监控保障。

高并发写入热点行,本质是大量请求争抢同一行记录的行锁,导致串行化执行、事务堆积、CPU飙升。单纯靠数据库调优效果有限,必须结合缓存与数据结构改造来分散压力。核心思路就两条:一是把“实时写库”变成“异步写库”,二是把“单点更新”变成“多点并行”。
用 Redis 缓存+批量落库,隔离写压
不直接让每笔请求更新 MySQL,而是先在 Redis 中完成原子操作,再由后台任务按批次同步到数据库。
- 用户行为(如点击、下单、计数)统一调用
INCR或DECRBY更新 Redis 计数器,毫秒级响应 - 用定时任务(如每 2–5 秒)扫描所有相关 key,读取当前值,执行一次
UPDATE ... SET count = count + ? WHERE id = ? - 同步后清空 Redis 值,避免重复累加;若需强一致性,可加版本号或时间戳做幂等校验
对热点行做逻辑分片,变“一行锁”为“多行锁”
把原来一个 ID 对应的一条记录,拆成 N 条带分片标识的记录,写入时随机或轮询选择分片,查询时聚合汇总。
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- 例如库存表原结构:
product(id PK, stock INT),改为product_stock(product_id, shard_id, stock, PRIMARY KEY(product_id, shard_id)) - 扣减时用
UPDATE product_stock SET stock = stock - 1 WHERE product_id = ? AND shard_id = FLOOR(RAND() * 16) - 查总库存改用
SELECT SUM(stock) FROM product_stock WHERE product_id = ? - 分片数建议 8–32,太少起不到分散效果,太多增加查询开销
搭配消息队列削峰,控制写入节奏
当业务允许毫秒级延迟时,用 Kafka/RocketMQ 接收写请求,消费者按固定速率消费,实现流量整形。
- 前端请求只发消息,不等 DB 结果,响应更快、失败率更低
- 消费者端做合并:同一商品 ID 的多次扣减请求,可聚合成一条
UPDATE ... SET stock = stock - N - 配合 Redis 预减库存(如
DECRBY stock_key N),防止超卖,也减轻 DB 校验压力
补充关键细节
这些方案不是孤立使用的,实际中常组合落地:
- Redis 缓存用于快速响应和前置校验,分片表用于持久化存储,消息队列用于解耦与限流
- 分片逻辑尽量放在应用层,避免数据库函数(如
RAND())影响执行计划稳定性 - 所有方案都要配套监控:Redis 内存水位、消息积压量、分片间数据倾斜度、DB 慢日志中的
Waiting for table metadata lock等










