分库分表学习1
2023-08-24 01:15:13 0 举报
AI智能生成
这是一篇分库分表的学习。这是一篇分库分表的学习。这是一篇分库分表的学习。这是一篇分库分表的学习。这是一篇分库分表的学习。
作者其他创作
大纲/内容
参考自
https://mp.weixin.qq.com/s/J_zVlrR9cDX9Vrg6YVjUiA
怎么分
水平分表:将表数据按记录分到多个表<i>(涉及<b>分片策略</b>)</i><br>
垂直分表:将表数据按字段分到多个表
分表策略
id范围分表
是什么
假设每张分表能放2kw行数据。那user0就放主键id为1~2kw的数据。<br>user1就放id为2kw+1 ~ 4kw,user2就放id为4kw+1 ~ 6kw, <br>userN就放 2N kw+1 ~ 2(N+1)kw<br>
假设现在有条数据,id=3kw,将这个3kw除2kw = 1.5,向下取整得到1,<br>那就可以得到这条数据属于user1表。于是去读写user1表就行了。<br>这就完成了数据的<b>路由逻辑</b>,我们把这部分逻辑封装起来,放在数据库和业务代码之间。<br>
优点
数据少的时候 表也少,数据增多的时候表会慢慢增多<br>
支持无限扩展
缺点
根据id范围去做分表,因为id是递增的,那新写入的数据一般都会落到某一张表上,如果你的业务场景写数据特别频繁,那这张表就会出现<b>写热点</b>的问题
id取模
是什么
一个id=31进来,我们一共分了5张表,分别是user0到user4。对31%5=1,取模得1,于是就能知道应该读写user1表
优点
新写入的数据都是实实在在的<b>分散</b>到了多张表上
缺点
如果想要扩展表的个数,比如从5张表变成8张表。那同样还是id=31的数据,31%8 = 7,就需要读写user7这张表。<br>跟原来就对不上了。这就需要<b>考虑数据迁移</b>的问题<br>
id范围+id取模
是什么
<b>可以在某个id范围里,引入取模的功能。<br></b><i>(比如 以前2kw~4kw是user1表,现在可以在这个范围再分成5个表,也就是引入user1-0, user1-2到user1-4,在这5个表里取模。<br>举个例子,id=3kw,根据范围,会分到user1表,然后再进行取模 3kw % 5 = 0,也就是读写user1-0表。)</i>
路由策略
第三方orm库,放在<b>客户端侧</b><i>(需要根据不同的语言实现不同的代码库,常用组件有sharding-jdbc)</i>
在mysql和业务代码之间加个<b>proxy服务</b><i style="">(</i><i>不需要关心上游服务用的是什么语言,常用组件有MyCat)</i><br>
读扩散问题
背景
上面分表策略用了id这一列作为分表的依据,这其实就是所谓的<b>分片键</b>。实际上我们一般也是用的数据库主键作为分片键。<br>但很多情况下,我们的查询又不是只查主键,如果我的数据库表有一列name,并且加了个普通索引。<br>由于name并不是分片键,我们没法定位到具体要到哪个分表上去执行sql。<br>于是就会对所有分表都执行上面的sql,当然不会是串行执行sql,一般都是并发执行sql的。<br>如果我有100张表,就执行100次sql。<br>如果我有200张表,就执行200次sql。<br>随着我的表越来越多,次数会越来越多,这就是所谓的读扩散问题。<br>
问题核心
主键是分片键,而普通索引列并不分片<br>
怎么解决
单独建个新的分片表<i>(这个新表里的列就只有旧表的主键id和普通索引列,而这次换<b>普通索引列来做分片键</b>。)</i>
例子:为name列建个新表(nameX),以name为新的分片键
缺点
<b>需要维护两套表</b>,并且普通索引列更新时,要两张表同时进行更改。有一定的开发量。
更优解
分析
<i>上面的方案,则通过引入一个新表,倒过来,先用name查到对应的id,再拿id去获取具体的数据。<br>这其实就像是建立了一个新的索引一样,像这种,通过name列反查原数据的思想,其实就很类似于<b>倒排索引</b></i><br>
方案
使用<b>es</b>,es天然分片,而且内部利用倒排索引的形式来加速数据查询
<b>ES+MySQL。通过开源工具 canal 监听mysql的binlog日志变更,再将数据解析后写入es</b>
更更优解
使用<b>tidb</b>
这是个分布式数据库。它通过引入Range的概念进行数据表分片,比如第一个分片表的id在0~2kw,第二个分片表的id在2kw~4kw。<br>这是根据id范围进行数据库分表。它支持普通索引,并且普通索引也是分片的,这是不是又跟上面提到的倒排索引方案很类似。<br>
总结
1 mysql在<b>单表数据过大</b>时,查询性能会变差,因此当数据量变得巨大时,需要<b>考虑水平分表</b>
2 水平分表需要选定一个<b>分片键</b>,一般选择主键,然后根据id进行取模,或者根据id的范围进行分表
3 mysql水平分表后,对于非分片键字段的查询会有<b>读扩散</b>的问题,可以用普通索引列作分片键建一个新表,先查新表拿到id后再回到原表再查一次原表。<br>这本质上是借鉴了倒排索引的思路<br>
4 如果想要支持更多维度的查询,可以监听mysql的binlog,将数据写入到<b>es</b>,提供近实时的查询能力
5 用tidb替换mysql也是个思路
0 条评论
下一页