一、 数据库从单击到分布式会面临的问题
思考方向: 单机的CRUD扩展到多机后面临的问题、原来依赖的单机数据库特性不在可用(自增id、事务处理...)
如:基本的sql语句select <columnName1>, <columnName2>.. from <tablename> where xx join <tablename2> on <condition> order by yy 其逻辑表分布在不同数据库不同表的时候,需要进行的各种处理
- 垂直、水平拆分
a. 单机的ACID被打破,事务难搞
b. join操作变得比较困难、外键关联
c. 单库的自增序列生成唯一ID需要自己实现
d. 逻辑表的查询需要跨库 - CAP / Base
a. CAP
i. Consistency 一致性
ii. Availability 可用性
iii. Partition-Tolerance 分区容忍性
b. Base模型
i. Basically Available 基本可用,允许分区失败
ii. Soft state 软状态,接受一段时间的状态不同步
iii. Eventally consistent 最终一致,保证最终数据的状态是一致的 - 分表分库后的查询
a. 跨库join
i. 把数据库的join分成多次数据库操作,然后在应用层合并数据
ii. 数据冗余,把原来需要join的操作变成单表查询,需要结合具体的业务场景做冗余处理
iii. 借助外部系统,如搜索引擎
b. 排序、函数处理、聚合操作
c. 非排序分页: 等比/等步长获取
d. 排序后分页: 需要获取2倍页号的数据量
二、数据访问层的设计
主要围绕上图所示的6个步骤,除了SQL执行外其他5个步骤分布式数据访问层介入
- sql解析得到sql中关键信息,如表名、字段、where条件等
- 然后根据参数和规则处理确定目标数据源连接
a. 固定hash算法
b. 一致性hash算法 + 虚拟节点
c. 映射表与规则自定义计算 - 一般原则是分库后尽可能避免跨库查询, 但是在必要的时候还是需要进行sql改写的,比如一些聚合查询分表后的逻辑表
- 数据源选择, 一写多读 / 多写多读的情况选择哪个数据库连接
- Sql执行
- 结果集返回并合并
后续深入:
- 分布式事务 XA、Paxos协议
- 使用并研究ctrip dal的实现思路
- 一致性hash算法实现
- java开源分布式数据中间件
- 数据库拆分案例,拆分方式以及灰度过渡处理方式