整体分层思路:库架构分治(分库分表)→ 读写分离 → 缓存削峰 → 事务 / 锁优化 → SQL / 索引优化 → 限流降级兜底,适配 Java SpringBoot/MyBatis/MyBatis-Plus 技术栈。
一、基础架构:读写分离(解决读多写少并发瓶颈)
1. 架构模型
1 主 N 从:主库负责写(Insert/Update/Delete),从库负责查询
同步方式:MySQL 半同步复制(避免主从延迟过大)
主从数量配比:常规 1 主 2 从;读压力极大 1 主 4~8 从
2. Java 层落地实现
方案 1:MyBatis-Plus / Spring AbstractRoutingDataSource 动态数据源
自定义注解 @Master(走主库)、@Slave(走从库),AOP 拦截方法切换数据源。
java
运行
// 写操作强制主库
@Master
public void createOrder(OrderDTO dto) {
orderMapper.insert();
}
// 查询走从库
@Slave
public Page<OrderVO> listOrder(Long userId) {
return orderMapper.selectPage();
}
方案 2:中间件代理(推荐高并发)
Sharding-JDBC(客户端分片,无中间件单点,Java 原生集成)
MyCat(独立中间件,统一数据库代理,适合多语言后端)
3. 主从延迟解决方案(高并发核心痛点)
强制读主:新增数据立刻查询场景(创建订单后查详情),注解强制走主库
业务缓存兜底:写入主库同时更新 Redis,查询优先读缓存,规避延迟
半同步复制:主库写入成功必须等至少一台从库接收 binlog 再返回客户端
避免长事务:主库大事务会阻塞 binlog 同步,导致从库严重滞后
二、水平扩展:分库分表(解决单库单表百万 / 千万级数据瓶颈)
1. 分库分表两种模式
垂直拆分(业务维度拆分)
按业务模块拆库:订单库、用户库、商品库、支付库
优点:业务隔离,互不锁库,单库压力降低
适用:系统业务模块清晰、耦合低
水平拆分(数据量维度拆分,高并发必备)
同一业务表,按分片键拆分多张表 / 多个库,比如订单表 t_order_00 ~ t_order_31
分片键选择黄金标准
高频查询条件(userId、orderId)
均匀分片,避免数据倾斜
极少跨分片关联查询
分片算法(Sharding-JDBC 原生支持)
取模分片(最常用)
分片键 % 分片总数,例如用户 ID%32,均匀分布 32 张表范围分片(时间分片,订单 / 日志)
按创建时间分:按月分表
t_order_202601、t_order_202602优点:范围查询友好;缺点:热点月份数据倾斜,搭配冷热数据分离
2. Sharding-JDBC Java 落地核心配置
核心能力
读写分离 + 分库分表一体化
分布式主键(雪花算法 Snowflake,Java 内置,全局唯一 ID)
分布式分页、聚合函数、跨库关联查询适配
避坑要点
禁止无分片键查询:会触发全表扫描,并发直接打满数据库
跨分片事务:MySQL 不支持分布式强事务,优先最终一致性
分页 offset 过大:分表分页必须通过分片键过滤,禁止大偏移分页
3. 冷热数据分离(海量历史订单)
热数据:近 3 个月订单,分库分表在线读写
冷数据:超过 3 个月历史订单,归档至归档库 / ClickHouse,线上业务不查询
定时任务(XXL-Job)迁移冷数据,降低主库存储、索引压力
三、缓存体系:数据库前置削峰(高并发第一道防线)
核心逻辑:缓存扛 90% 读请求,数据库只处理写和少量强一致查询
1. 多级缓存架构
本地缓存(Caffeine)
Java 进程内存缓存,毫秒级,无网络开销;适合字典、配置、热点商品基础信息
过期策略:写入更新缓存 + 定时淘汰,避免数据不一致
分布式缓存(Redis Cluster 集群)
架构:Redis 3 主 3 从集群,分片存储热点数据
存储内容:用户会话、订单详情、商品库存、计数类数据
数据库兜底:缓存失效 / 穿透时才查询数据库
2. 缓存三大并发问题解决方案
缓存穿透(查询不存在数据,绕过缓存打数据库)
方案:布隆过滤器(Redis)、空值缓存、参数校验拦截非法 ID
缓存击穿(热点 Key 过期,大量请求击穿数据库)
方案:互斥锁(Redis SETNX)、热点永不过期、逻辑过期
缓存雪崩(大量 Key 同时过期,数据库瞬间压垮)
方案:过期时间随机偏移、Redis 集群高可用、熔断限流
3. 缓存与数据库双写一致性(Java 业务标准流程)
标准流程(推荐):先更新数据库,再删除缓存
@Transactional
public void updateOrder(Order order) {
// 1. 更新主库数据库
orderMapper.updateById(order);
// 2. 删除Redis缓存,下次查询自动加载最新数据
redisTemplate.delete("order:" + order.getId());
}
强一致场景:分布式锁锁住读写操作,保证更新 + 删缓存原子性
四、事务与并发锁设计(避免超卖、脏写、数据不一致)
1. 事务选型
单机本地事务:单库使用 Spring @Transactional,REPEATABLE READ 隔离级别(MySQL 默认)
分布式事务(跨库 / 分库场景)
高并发禁止强一致性 2PC(Seata AT 性能差),分层选型:
最终一致性(首选):Seata TCC / 本地消息表 + 定时任务补偿(订单支付、库存扣减)
可靠消息队列:RocketMQ/Kafka 事务消息,解耦削峰
2. 并发控制锁方案(按并发量从小到大)
1)乐观锁(高并发读、少写场景,无数据库阻塞)
基于版本号实现,Java MyBatis 示例:
sql
update t_order set status=1,version=version+1
where order_id=#{id} and version=#{oldVersion}
适用:商品库存、订单状态流转,无锁竞争,性能极高
2)悲观锁(写竞争极强、不允许失败场景)
行级锁:
select ... for update,只锁定单行,并发友好;必须命中索引,否则升级表锁表锁:禁止高并发使用,会阻塞全表读写
3)分布式锁(跨服务 / 分库场景)
Redis 分布式锁(SET + EX + NX,Redisson 封装,Java 首选),支持可重入、锁超时自动释放
Zookeeper 临时节点锁:一致性更强,性能低于 Redis,适用于极低并发强一致场景
五、SQL、索引、连接池优化(Java 应用层基础优化)
1. 索引设计规范(MySQL 高并发核心)
分片键、查询条件、关联字段建立联合索引,遵循最左前缀
避免回表:覆盖索引(SELECT 只查索引字段,不查 *)
禁止索引失效操作:函数运算、隐式转换、like % xxx、not in、or
大字段(text、blob)拆分至附属表,避免索引臃肿、分页缓慢
2. SQL 编写约束(Java MyBatis 强制规范)
禁止大事务、批量超大 Inset/Update,拆分分批操作
禁止多表笛卡尔积关联,分库分表禁止跨库 join
分页禁止 limit 100000,10;改用主键游标分页
where id > lastId limit 10批量操作使用 MyBatis batch 模式,减少网络 IO
3. Java 数据库连接池(HikariCP,SpringBoot 默认)
高并发参数调优核心:
yaml
spring:
datasource:
hikari:
maximum-pool-size: 20 # 最大连接数,CPU核心数*2~5,避免过大导致MySQL连接耗尽
minimum-idle: 5
idle-timeout: 300000
connection-timeout: 20000
max-lifetime: 1800000
优化点:连接数不要盲目调大;SQL 执行超时熔断;监控连接泄露
六、高并发流量兜底:限流、熔断、降级
数据库承载能力有限,不能无限承接流量,Java 微服务配套防护:
接口限流:Guava RateLimiter 本地限流 + Redis 分布式限流,限制每秒请求量
熔断降级(Sentinel)
数据库查询超时 / 报错比例达到阈值,触发熔断,直接返回缓存 / 默认数据,不再访问数据库
非核心业务降级:商品评论、日志查询直接返回空,保护订单、支付核心库
请求队列削峰:高并发写请求(下单、扣库存)通过 MQ 异步削峰,同步转异步,平缓写入数据库
七、高可用架构设计(避免数据库单点故障)
主库高可用:MGR MySQL 组复制 / Keepalived 虚拟 IP,主库宕机自动切换从库为主,Java 无感知
从库多副本:至少 2 台从库,一台故障自动路由其他从库
定时数据备份:全量备份(mysqldump)+ binlog 增量备份,支持故障数据回滚
监控告警:Prometheus + Grafana 监控指标:慢 SQL、连接数、锁等待、主从延迟、QPS,异常短信告警
八、不同并发量级完整落地组合方案
1. 百万日活,QPS < 2000(中小型项目)
单库主从读写分离 + Redis 分布式缓存 + HikariCP 优化 + 乐观锁,无需分库分表
2. 千万日活,QPS 2000~10000(中大型电商)
读写分离 + Sharding-JDBC 水平分表(按 ID 取模)+ Redis Cluster 多级缓存 + Seata TCC 分布式事务 + Sentinel 熔断限流
3. 超大型平台,QPS > 10000,亿级数据
多主多从分库集群 + 时间范围分片 + 冷热数据归档 ClickHouse + MQ 全异步写 + 本地消息表最终一致性 + 全链路限流熔断
九、高频踩坑总结
分表无分片键查询,全表扫描拖垮数据库
主从延迟不做缓存兜底,用户查询旧数据
热点商品无缓存,秒杀流量直接压库
大事务、长 SQL 导致行锁升级表锁,并发卡死
连接池最大连接数设置过大,MySQL 连接耗尽拒绝连接
分布式事务使用 2PC,高并发下性能雪崩