架构师方案-分库分表

前言

分库分表是一个老生常谈的问题,但网上的大多数文章只是概要式讲述,一些核心步骤一笔带过。 这篇文章给大家讲述所有可行性方案的同时,系统性、完整性阐述其思想内核。

1. 拆分形式

分库分表拆分形式分为垂直分库分表和水平分库分表,这篇文章将聚焦于水平分库分表
原因在于组织、业务划分的之初或者大数据量之前,在一些开发人员素质比较高的公司,库、表先天的就垂拆分的比较清晰了,剩下只是数据字段微调。 水平分库分表是侧重于技术的问题,垂直分库分表是侧重于业务划分问题。注意是侧重,为啥这么说了,以订单表为例,用户下单是订单补充信息过长,把它拆分出来,放在其它数据库里,用订单号关联,这是垂直拆分的一种形式,但显然对业务操作没什么影响。

从上我们可以得出,大数据量下必然要水平分库分表,不一定要垂直分库分表。

image.png

image.png

2.切分策略

2.1 取模切分(Hash取模)

我们一般会用对某个路由Key的Hash值取模,使数据分散到各个表中更加均衡。

比如原始订单表信息,我们把它分成4张分表:

image.png

优点:可以较为均匀的将数据切分,不会有热点问题

缺点:扩容时需要重新计算切分后的值,涉及到大量的数据迁移

2.2 Range切分

image.png

优点:单表大小可控,天然水平扩展。
缺点:无法解决集中写入瓶颈,有热点问题。

2.3 查询切分

image.png

查询切分的好处,是可以解决Hash取模的水平扩展问题和Range切分的热点问题。

2.3.1基于查询配置结合ShardGroup方式解决水平扩展问题和热点问题
(1)表数据演示
image.png
image.png
image.png

总得来看表结构呈现share group->share db->share table的树形结构

(2) 核心流程
image.png

step1:通过id所处的范围找到group_id
step2:通过id取模和groupid找到db_id
step3:通过id所处的范围和db_id找到table_id

优点:理论上根据数据实际增长情况,调整ID和库、表的Mapping关系,将hash和range结合起来可以解决热点和水平扩展问题。
缺点:引入额外的配置表,降低性能,有漏配、错配的风险。

2.4 一致性Hash切分

image.png
  1. 建立一个2^32 hash节点环,计算database的hash值(常用:hash(节点前缀 +(ip+端口))%2^32),并映射到hash环的具体位置
  2. 将待切分数据取值hash(sharding key) % 2^32,映射到hash 环上,并按照规则从root节点开始顺时针查找
if hash(node_0) %2^32 < hash(sharding key) %2^32 <= hash(node_1) %2^32 ;该数据归属 node_1(database1)
if hash(node_1) %2^32 < hash(sharding key) %2^32 <= hash(node_2) %2^32 ;该数据归属 node_2(database2)
if hash(node_2) %2^32 < hash(sharding key) %2^32 <= hash(node_3) %2^32 ;该数据归属 node_3(database3)
...
  1. 扩容时迁移数据时,如新增节点node_4(database4) 在node_1和 node_2之间,则需要将data_key落在node_1到 node_4的数据从原node_2(database2)迁移到node_4(database4)
image.png

优点:扩容时只需要迁移小部分的数据

缺点:如果节点不够分散,会出现Hash环的倾斜,导致节点数据不均匀

增加虚拟Hash节点解决数据倾斜问题
image.png

基于一致性Hash 增加了虚拟节点,这些节点会映射到真实的物理节点,这样就可以调控节点数据分配

优点:减少了Hash环倾斜带来的影响

缺点:增加复杂度

3.数据迁移

数据库拆分一般是业务发展到一定规模后的优化和重构,为了支持业务快速上线,很难一开始就分库分表,这时候就需要进行数据迁移了。

3.1同步脚本停机迁移(不建议)

写个脚本老库的数据写到新库中。比如,在系统使用的人数非常少的时候,凌晨1点,挂一个公告说系统要维护升级预计N小时。个脚本将老库的数据都同步到新库中。
优点:操作简单
缺点:一但数据量大,加上数据核对时间,迁移时间会超出公告时间。

3.2 双写数据迁移

3.2.1 在业务代码中直接双写
Step1.数据库双写(事务成功以老模型为准),查询走老模型。
image.png

旧数据如何迁移到新库?
通过job导历史数据写入到新库,同时建立映射关系。

如何保证新库里的数据是最新且完整的?
我们对老库的更新操作(增删改),同时也要写入新库(双写)。如果操作的数据不存在于新库的话,需要插入到新库中。同时每日job数据对账,并将差异数据补平。这样就能保证,咱们新库里的数据是最新且完整的。

不在同一库如何保证事务?
只保证旧库写入事务,差异数据由数据对账服务补偿。

Step2.数据库双写,但是事务成功与否以新模型为准,在线查询切新模型。

在历史数据导入完毕并且数据对账无误后,执行该步骤。


image.png

如何查询旧订单?
通过order mapping数据找到新库id,在新库中查询。

Step3.老模型不再同步写入,在线查询切新模型。

在查询无异常后,执行该步骤。

image.png

在业务代码中直接双写方案
优点:平滑迁移
缺点:双写影响响应时间,减少吞吐量

3.2.1 通过数据同步工具双写

数据同步数据同步整体方案见下图

image.png

上述方案中不难发现,业务写一条数据到旧实例的一张表,于是产生了一条binlog;data-sync中间件接到binlog后,将该记录写入到新实例,于是在新实例也产生了一条binlog;此时data-sync中间件又接到了该binlog......不断循环

如何解决双向同步时的binlog循环消费问题?

采用数据染色方案解决,只要能够标识写入到数据库中的数据使data-sync中间件写入而非业务写入,当下次接收到该binlog数据的时候就不需要进行再次消息流转。所以data-sync中间件要求,每个数据库实例创建一个事务表,该事务表tb_transaction只有id、tablename、status、create_time、update_time几个字段,status默认为0。操作如下:

# 开启事务,用事务保证一下sql的原子性和一致性
start transaction;
set autocommit = 0;
# 更新事务表status=1,标识后面的业务数据开始染色
update tb_transaction set status = 1 where tablename = ${tableName};
# 以下是业务产生
binloginsert xxx;update xxx;update xxx;
# 更新事务表status=0,标识后面的业务数据失去染色,后面业务正常继续消费
update tb_transaction set status = 0 where tablename = ${tableName};
commit;
image.png

数据同步工具DTS


image.png

4.平滑扩容

4.1 全局增量分区局部散列扩容方案

对于Range和查询切分切分策略,增加数据库实例和映射配置即可

4.2 基于主从同步的扩容方案

核心思想是,启动更多的从服务器(取决于希望扩容的服务器量),当从服务器从主服务器同步完成之后,将所有从服务器升级为主服务器,然后调整路由规则,再根据路由规则删除每个主服务器中的冗余数据

image.png

4.3 基于数据迁移的扩容方案

上文数据迁移中,通过数据同步工具双写就是此方法。数据迁移的过程中就涉及到了平滑扩容,我在这里把它拿出来,是为了大家更好理解它。

image.png

4.查询问题

4.1 数据多维度查询

水平切分后,查询的条件一定要在切分的维度内,比如查询具体某个用户下的各位订单等;禁止不带切分的维度的查询,即使中间件可以支持这种查询,可以在内存中组装,但是这种需求往往不应该在在线库查询,或者可以通过其他方法转换到切分的维度来实现。

但是我非要多维度查询怎么办?
4.1.1 多维度查询双写

比如,对于订单表我可以同时以user_id、order_id为sharding key冗余分库分表数据。
优点:查询实时性
缺点:写入性能有影响,数据冗余

4.1.2 增加全局二级索引库

每个全局二级索引库对应一张分布式索引表,和其他分布式表一样,按照指定的分区规则水平拆分为多张物理表。


image.png

优点类似ES 倒排索引,首先通过value 找到id,在通过id找到完整数据。
优点:查询实时性,相较于数据冗余
缺点:写入性能有影响,数据冗余

4.1.3 通过binlog数据异构查询

比如,可以把mysql通过binlog写入到OLAP数据库,比如Elasticsearch、 Clickhouse查询。
优点:读写分离,方便支持多维度或者全字段索引
缺点:查询会有实时性问题,可以用于非实时场景

4.2 order排序查询

基于上述分片聚合方式我们清晰的了解到如何可以进行跨分片下降数据获取到内存中,但是通过图中结果可以清晰的了解到返回的数据并不像我们预期的那样有序,那是因为各个节点下的所有数据都是仅遵循各自节点的数据库排序而不受其他节点分片影响。 那么如果我们对数据进行分片聚合+排序那么又会是什么样的场景呢

4.2.1 内存排序

todo

4.2.2 流式排序

todo

5.灰度发布

后续在补充。。。

6.总结

分库分表要考虑的细节还是很多的,所有才有了NewSql数据库,但是上面这些解决方案,还是需要掌握的。

参考

https://blog.csdn.net/mouzeping123/article/details/120061298
https://tech.meituan.com/2016/11/18/dianping-order-db-sharding.html
https://cloud.tencent.com/developer/article/2124399
https://mp.weixin.qq.com/s?https://juejin.cn/post/7085132195190276109
https://bbs.csdn.net/topics/605500717
https://blog.51cto.com/u_11475121/2954464
https://zhuanlan.zhihu.com/p/635219596

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345

推荐阅读更多精彩内容