Appearance
架构实战经验
高性能架构
冷热分离
根据业务状态,对适合的业务表做冷热分离。终态数据不常使用,只读不写。接受冷热数据分开查询,无同时读取数据需求。无复杂查询要求和快速响应要求。
1. 判断冷热
- 时间维度
- 状态维度
- 组合状态
2. 触发分离
- 状态转移时(代码侵入,监听数据库)
- 定时扫描(跟时间相关)
3. 如何分离
- 判断(判断 + 持久化)
- 转移冷库(状态迁移,覆盖遗漏,幂等唯一不重复)
- 删除热库
一致性(最终一致性,容错):
- 添加重试
- 幂等
数据量:
- 分批处理
- 状态转移触发不需要考虑
并发性:
- 多线程加速
- 数据隔离
- 先锁定数据,锁超时,再 update
4. 如何使用
- 入口区分
5. 历史数据迁移
- 分批迁移方案,只需要执行一次历史数据标记,就可以启动老数据迁移。
- 状态转移触发,则需要对所有历史数据的最终态做一次迁移,可能需要停机。
6. 后续冷库优化
- 修改成 OLAP 数据库,支持简单条件查询
- HBase
- Doris
读写分离
主要解决高并发的问题。
查询分离
写效率尚可,解决查询慢、关联表多、历史数据多、所有数据任何时候都可能被修改和查询。
1. 触发
- 写入时触发,有代码入侵
- 写入时触发,异步发起更新,有代码入侵
- 监控数据库,日志触发,业务复杂时难以穷举
2. 实现查询分离
- 数据更新
need_update - 发送 MQ
- 消费者获取 MQ
- 查询
need_update=true - 将查询的数据更新到查询库
- 更新
need_update=false - 回调告知消费完成
采用 MQ 触发查询更新(解耦,异步):
- 入库线程限制
- 自动重试
- 并发场景
MQ 带来的问题:
- 选型
- MQ 宕机
- 消息重复投递
- 消息丢失问题
建议:
- 数据标识来触发,而不是通过 id(
need_update) - 批量查询,批量更新标识,保证幂等性操作
- 先锁定数据,锁超时,再 update,解决并发问题
- 时序性问题:
- 业务 id 作为 key,保证相同业务顺序执行
- 引入
update_time或版本号,如果发现版本号或者update_time倒退,就再次触发同步
3. 存储
- ES:侧重全文检索、相关度排序。数据需要整理成一整条数据。
- Doris:侧重 SQL 适配,OLAP
- MongoDB:文档非结构化
4. 使用
- 查询数据可能存在延迟
5. 历史数据
- 修改
need_update=true - 分批渐进式处理
拆分存储
选型
- 数据库分区
- NoSQL
- NewSQL
- 分库分表
MongoDB
文档数据库,非约束关系型数据库,没有事务,稳定性需要结合场景评估。
NewSQL
- OLTP:TiDB、PolarDB、OceanBase
- HTAP:Doris、TiDB + TiFlash、ClickHouse
- 冷数据新范式:S3/OSS + Trino/Dremio,AnalyticDB for MySQL
分库分表
- 组装动态 SQL
- 数据库路由
- 结果合并
技术模式:
- 代理模式
- 客户端模式
分片涉及要点
- 分片主键,根据业务需求选择字段
- 分片策略
- 范围分片
- Hash 分片
- 混合分片(先范围再 hash)
- 业务代码如何修改
- 对微服务影响更小,建议拆分微服务
- 读数据考虑避免跨库跨表
- 历史数据迁移
- 存量直接迁移,增量监听数据库日志
- 验证数据全量
- 未来扩容方案
秒杀设计
多级分流
1. 接入层
- 客户端缓存
- 强制缓存和协商缓存
- 动静分离
- 静态资源 CDN 缓存
- 网关做限流、熔断、降级、黑白名单
- 流量做负载均衡:LVS、Nginx、HAProxy、Keepalived
- 传输链路优化:
- keep-alive
- 多路复用
- 即时压缩
- 快速 UDP 连接
2. 应用层
- 核心业务拆分成微服务,不互相影响
- 核心业务做无状态,便于快速弹性伸缩
- 异步化,流量削峰,MQ
- 服务端缓存
- 缓存属性
- 缓存风险
3. 持久层
- 拆分存储
- 读写分离
业务超卖
前置拦截
- 进一步请求准入控制
- 做限流
- 推荐令牌桶
锁机制
- Redis + Lua
- 乐观锁
- 悲观锁
最终一致性
- 事务消息
- 对账补偿
下单锁定,支付锁定,下单锁定超时释放
缓存场景
查询优化
写入优化
写缓冲
- 预约场景
- WAL 的思想引入缓冲层
- 日志收集埋点场景
高可用架构
限流熔断
- 原理:限流在入口处拦截过载流量;熔断在调用端切断故障下游,防止雪崩。
- 关键点:限流保护自己,熔断保护下游和整体链路。
冗余 Failover
- 原理:任何组件都至少部署两个以上节点,消除单点故障(SPOF)。
- 关键点:配合 Keepalived 或 Sentinel 实现故障自动转移。
去中心化
- 原理:移除中心化管理节点(Master),采用 P2P 或 Gossip 协议,避免 Master 成为瓶颈或单点。
- 关键点:如 Redis Cluster、Cassandra、Blockchain,节点地位对等。
高可扩展
微服务架构
- 原理:将单体应用按业务领域拆分为独立部署服务,实现开发、部署、扩容的解耦。
- 关键点:服务粒度控制,避免分布式事务带来的复杂性。
事件驱动架构
- 原理:生产者和消费者通过中间件交互,互不感知,实现逻辑解耦和流量削峰。
- 关键点:消息的可靠投递和幂等性处理。
无状态设计
- 原理:服务节点不存储会话状态(Session),状态外置(Redis/JWT),使节点可随意扩展。
- 关键点:JWT 换取空间换时间,Redis Session 换取时间换空间。
混合方案
- Access Token (JWT) + Refresh Token (存 Redis)
- JWT 携带最小化信息 + 局部查库
微内核 + 插件
Spring Cloud + k8s 缺点
- 认知负担、学习成本
- 资源消耗更大,采用代理的话调试困难,开发体验差
- 平台耦合,耦合 k8s 这一套
- k8s 拓展功能并不丰富,四层代理的基础在服务治理上并不强大,ELK 也适配不好
Elasticsearch 数据持久化流程
Elasticsearch 通过 内存缓冲 + 事务日志(Translog)+ 定期刷盘 实现高性能与数据可靠性的平衡。
持久化步骤
- 写入 Translog
- 写入内存缓冲区(Indexing Buffer)
- Refresh(默认每 1 秒)
- Flush(定期或触发条件满足时)
- Merge(后台自动)
可调参数
index.translog.durabilityindex.translog.sync_intervalindex.translog.flush_threshold_sizeindex.refresh_intervalindices.memory.index_buffer_sizeindex.translog.flush_threshold_period
建议:生产环境保持
translog.durability=request以确保数据安全;批量导入时临时关闭 refresh 提升性能。
深度分页问题
max_result_window- Search After
- Scroll API
- 业务层优化
常见策略:
- 禁止深度翻页
- 改用“加载更多”
- 预聚合 / 分桶
- 异步导出