数据库选型策略
数据模型
数据库类型 | 数据模型 | 典型场景 | 代表产品 |
---|---|---|---|
关系型数据库(RDBMS) | 表格结构,强Schema约束 | 事务处理(OLTP)、复杂查询 | MySQL、PostgreSQL、Oracle |
文档数据库 | JSON/BSON文档,弱Schema | 灵活模式、半结构化数据存储 | MongoDB、Couchbase |
键值数据库 | Key-Value存储 | 高速缓存、会话管理 | Redis、DynamoDB |
列式数据库 | 按列存储,压缩率高 | 数据分析(OLAP)、大规模聚合 | Cassandra、HBase、ClickHouse |
图数据库 | 节点与关系存储 | 社交网络、推荐系统、欺诈检测 | Neo4j、ArangoDB |
时序数据库 | 时间序列数据优化 | 物联网监控、日志存储、指标分析 | InfluxDB、TimescaleDB |
搜索引擎数据库 | 全文检索、相关性排序 | 商品搜索、日志分析 | Elasticsearch、Solr |
业务场景
-
OLTP(联机事务处理) :
- 特点:高并发短事务,强一致性,频繁增删改。
- 选型:关系型数据库(如MySQL)、NewSQL(如TiDB)。
-
OLAP(联机分析处理) :
- 特点:复杂查询,大数据量聚合,读多写少。
- 选型:列式数据库(如ClickHouse)、MPP数据库(如Snowflake)。
-
HTAP(混合事务与分析处理) :
- 特点:兼顾事务与分析需求。
- 选型:NewSQL(如TiDB)、云原生数据库(如Google Spanner)。
技术特性
-
一致性:
- 强一致性(CP):金融交易(如MySQL ACID)。
- 最终一致性(AP):社交网络评论(如Cassandra)。
-
扩展性:
- 垂直扩展(Scale-Up):单机性能强(如Oracle)。
- 水平扩展(Scale-Out):分片与多副本(如MongoDB)。
-
事务支持:
- 单机事务:MySQL、PostgreSQL。
- 分布式事务:TiDB(Percolator协议)、CockroachDB(Spanner协议)。
选型决策框架
-
数据规模:
- 小数据量(<1TB):单机RDBMS(如PostgreSQL)。
- 大数据量(>1TB):分布式数据库(如Cassandra、TiDB)。
-
读写比例:
- 写密集型:LSM-Tree结构数据库(如HBase)。
- 读密集型:内存数据库(如Redis)或列式存储(如ClickHouse)。
-
延迟要求:
- 毫秒级响应:内存数据库(如Redis)、OLTP数据库(如MySQL)。
- 亚秒级响应:OLAP优化数据库(如BigQuery)。
分库分表实践
垂直拆分
-
垂直分库:按业务模块划分数据库(如用户库、订单库、商品库)。
- 优点:业务解耦,降低单库压力。
- 缺点:跨库事务复杂,需通过分布式事务(如Seata)解决。
-
垂直分表:将大表按列拆分(如用户表拆分为基础信息表、扩展信息表)。
- 场景:包含大量不常用字段(如用户备注、历史日志)。
水平拆分
- 水平分库:将同一业务数据按分片键分布到多个数据库(如订单库1、订单库2)。
- 水平分表:将同一表数据按分片键分布到多个子表(如
order_00
、order_01
)。
缓存策略优化
缓存读写策略
策略 | 流程 | 适用场景 | 优缺点 |
---|---|---|---|
Cache-Aside(旁路缓存) | 1. 读:先查缓存,未命中读DB并回填。 2. 写:直接写DB,删除缓存。 | 通用场景(如用户信息) | 实现简单,但存在缓存不一致风险(需结合延迟双删)。 |
Read-Through | 缓存作为代理,读请求由缓存处理,未命中时缓存自动从DB加载并返回。 | 缓存与DB强绑定(如ORM集成) | 简化业务逻辑,但缓存层需感知DB结构。 |
Write-Through | 写请求同时更新缓存和DB,由缓存层保证原子性。 | 对一致性要求极高的场景(如金融余额) | 写延迟高,需事务支持。 |
Write-Behind | 写请求先更新缓存,异步批量写DB(如定时刷新)。 | 写密集型场景(如日志、计数器) | 吞吐量高,但存在数据丢失风险(缓存宕机)。 |
缓存淘汰策略
策略 | 原理 | 适用场景 |
---|---|---|
LRU | 淘汰最近最少使用的数据(基于时间局部性原理)。 | 热点数据分布不均的长尾场景。 |
LFU | 淘汰访问频率最低的数据(基于计数统计)。 | 数据访问模式稳定的场景(如配置项)。 |
FIFO | 淘汰最早进入缓存的数据。 | 数据冷热无明显差异的流水场景。 |
TTL | 为每个Key设置过期时间,到期自动失效。 | 临时数据(如验证码、会话信息)。 |
Random | 随机淘汰数据。 | 极端场景下的兜底策略。 |
多级缓存架构
-
本地缓存 + 分布式缓存
- 本地缓存(L1) :使用Guava、Caffeine,缓存热点数据(毫秒级响应)。
- 分布式缓存(L2) :使用Redis、Memcached,共享全量数据(避免单机缓存穿透)。
-
同步机制:
- 主动推送:DB变更时,通过消息队列(如Kafka)通知各节点失效本地缓存。
- 被动失效:设置本地缓存短TTL(如5秒),依赖L2缓存兜底。
-
浏览器缓存 + CDN + 服务端缓存
- 浏览器缓存:通过
Cache-Control
、ETag
控制静态资源缓存(减少服务端请求)。
- CDN缓存:缓存图片、视频等静态资源,按区域就近分发。
- 服务端缓存:缓存动态数据(如API响应),通过Nginx或网关层实现。
- 浏览器缓存:通过
缓存穿透(Cache Penetration)
-
问题:大量请求查询不存在的数据(如不合法ID),绕过缓存直接冲击DB。
-
解决方案:
- 布隆过滤器(Bloom Filter) :在缓存层前置过滤器,拦截无效请求。
- 空值缓存:将查询结果为空的Key也缓存(设置短TTL,如30秒)。
缓存雪崩(Cache Avalanche)
-
问题:大量缓存同时过期,导致请求集中访问DB。
-
解决方案:
- 随机化过期时间:基础TTL + 随机值(如
TTL = 300 + rand(0, 60)
秒)。 - 永不过期 + 异步刷新:缓存不设TTL,后台线程定期更新(需处理脏读)。
- 随机化过期时间:基础TTL + 随机值(如
缓存击穿(Cache Breakdown)
-
问题:某热点Key失效的瞬间,高并发请求直接击穿到DB。
-
解决方案:
- 互斥锁(Mutex Lock) :第一个请求加锁查DB,后续请求等待锁释放后读取缓存。
- 逻辑过期:缓存Value中存储过期时间,业务判断是否需要异步更新。
数据一致性保障
强一致性(Strong Consistency)
-
定义:任何读操作都能读到最新写入的数据,所有节点数据实时一致。
-
实现方式:
- 同步复制:写入操作需所有副本确认后才返回成功(如ZooKeeper的ZAB协议)。
- 分布式锁:通过锁机制保证同一时刻仅一个客户端修改数据(如Redis RedLock)。
-
适用场景:金融交易、库存扣减等不允许数据不一致的场景。
最终一致性(Eventual Consistency)
-
定义:数据副本经过一段时间后达到一致,期间允许短暂不一致。
-
实现方式:
- 异步复制:写入主节点后异步同步到从节点(如MySQL主从架构)。
- 冲突解决:通过版本号(Vector Clock)或业务逻辑合并冲突(如购物车合并)。
-
适用场景:社交网络点赞、评论等容忍短暂不一致的场景。
其他一致性模型
模型 | 特点 | 案例 |
---|---|---|
因果一致性 | 有因果关系的操作按顺序可见,无因果关系的操作允许乱序。 | 聊天消息的顺序保证。 |
会话一致性 | 同一会话内的操作保证顺序一致性,跨会话允许延迟。 | 用户登录后的操作连贯性。 |
单调读一致性 | 用户读取的数据版本不会回退(如不会读到比之前更旧的值)。 | 新闻Feed流的分页 |