分库分表、分区分片、NewSql做比较
目录
一:分库分表
二:分区分片
三:NewSql
分库分表
一:什么情况下需要使用到分库分表
分表:
1.当热数据过多时,缓存不够,则压力会直接给到db,而db本身也是有一定数据量的
2.数据存储量较大时,会影响到sql性能.
分库:
当一个数据库实例撑不住时,就需要分散并发请求,且在降每一个实例压力的同时,对应每个表的sql也会提升性能.
二:分库分表实现方案
1.使用mysql的Merge引擎实现分表
1.1:一般都是事先没有考虑分表,也不想过多的改动代码,就会考虑这种方式.
1.2:mysql自带的引擎,可直接实现分表,会使用一张总表来管理多个从表.
1.3:所有的sql操作会通过总表然后分配给具体的子表进行crud操作.
1.4:查询数度比一张大表查询要快很多
1.5:缺点:
1.5.1:总表(MERGE表)必须使用MRG_MyISAM存储引擎,子表必须使用MyISAM存储引擎,MyISAM不支持事务操作.
1.5.2:会有一些MyISAM存储引擎的限制.
2.Range方式
类似于递增吧,有很多种方式,比如我列出几种:
1.每20万条数据是一张表,20万为基数,id为:1~20万=table1 21~40万=table2
2.和上同理,根据时间来:2020-01-02~2020-03-01=table1 2020-03-02~2020-06-01=table2
3.使用hash取余实现
这比较简单就是准备好除数和被除数
1:除数=id、code等 你想要的字段把他们hash成数字
2:被除数=基数=表的个数
3:最后算出余几 那么这条数据就是在table几
4.一致性hash
一致性Hash算法也是使用取模的思想,一致性Hash算法是对 2^32 取模。
所有节点0 ~ 2^32-1,这些数就相当于一个闭环,中间会穿插很多标示,标示代表着表的位置。
以顺序列出表的标示:
A1->A2->A3->A4
A1往前的数据为A2以此类推到A4的数据为A1达到一个闭环.
5.实现方案比较:
方案一Merge:
这个就看个人需求了,因为里面有很多缺点也不允许使用事物,
所以说如果表比较单一,且前期压根没考虑过分库分表,后面也不想更改代码,就可以尝试这种方案.
方案二Range:
比较适合增长数量较快的时候,因为可能需要频繁的扩容,
range对于库容还是相当简单的,加个表往后面追加就行,但是这样会有一个热点弊端,
一般一段时间插入的数据或者是新增的数据,会在之后的时间操作频繁一些,这样热点数据其实就分布的不均匀。
方案三hash:
hash结局了热点数据不均匀的问题,通过hash很简单的就能找到对应的节点,但是通过这种方式,如果需要增加节点,
或者减少节点,是需要全部遍历再重新分配的.这样会损耗大量时间.
例如 5%3余2要是增加了一个节点则为5%4余1
方案四一致性hash:
目前是最合适的方案,使用一个闭环,根据节点找到标示在找到具体的表.
用A1->A2->A3->A4举例子
如果需要删除A2节点,那么A2的数据迁移到A3即可
如果需要新增A5节点,则A5节点到A4节点中间的数据迁移到A4即可.
迁移量较少,但在节点少的时候,可能会发生一个节点占大多数的情况,这种情况就可以使用虚拟节点,这里就不详细写了,
因为一致性hash要是理解了,其实虚拟节点就更容易理解了.
三:垂直、水平分表
垂直一般很少用,除非字段过多过大,这样分割字段之后就能减少单表大小.
水平粗俗的理解就是数据量过大嘛,不大还分啥表.
四:分表后产生的问题
1.limit、order、sum
分开查询,在进行汇总以及处理.
2.ID重复
基于redis的原子性来获取id
新建一个服务来管理分配id,所有id通过rpc来获得
3.事物
3.1 2PC:先使用预执行,测试各事务是否能执行成功,可以的话,全部执行,其中有事务失败,则全部回滚.
不过可能会因为网络卡或者别的原因导致预执行成功,但实际执行有差异,这时也需要发送mq进行补偿或者进行别的处理.
缺点:占用资源,容易发生死锁.
3.2 TCC:和2PC一致,有准备阶段和提交回滚阶段,只不过他的准备阶段针对的不是数据库层,而是业务层,包括回滚阶段,也是业务层的回滚
好处在于更灵活,不会有io的阻塞,但加大了开发力度。
3.3 各模块mq的发送:需要执行的语句使用mq发送,给到对应的服务接口执行,不想上面两个方法是强一致性,这种方式是最终一致性,保证的是最终结果
好处:不会长时间锁住资源且开发不复杂
缺点:无法保证强一致性.
造成的问题:
1:空回滚
由于被调用方微服务出现宕机等问题,可能会发生try准备阶段未执行,就直接执行Cancel回滚。
解决:使用子事物id,记录try阶段状态,try执行过就正常执行Cancel操作,try没有执行则执行反正成功即可.
2:悬挂
由于网络延迟问题,Cancel回滚会在try准备阶段之前执行,这样就会造成问题.
解决:try在执行时,通过子事物id查询到Cancel回滚状态,如果Cancel执行,try执行退出,否则正常执行.
3:幂等性
这个很好理解了,就是在执行失败时,会有补偿操作,这样就会发生多次执行同一操作的情况.
解决:使用一个唯一标示来进行判断即可.
4.关联查询
关联的表可能会有多张无法确定的情况,可以使用冗余字段、表或者二次查询来组装数据。
可以把相关联的数据放在同一个库或者后缀名相同的表.
5.通过name等其他条件查询数据
可以利用缓存或者其他工具来进行name和id的映射,在通过id查询对应的数据.
只不过会多一层查询以及存储空间,这就需要自己去权衡利弊了,空间换时间,时间换空间的问题.
分区分片
将一个大表按分区在内部分成若干个小表.
可通过日期等条件来进行分区的划分,比如每年为一个区块.
一:分区表划分方案:
1.RANGE分区:行数据基于一个给定连续范围分区
p0 : 1000 代表0~999
p1 : 2000 代表1000~1999
p2 : 3000 代表2000~2999
2.LIST分区:同RANGE,区别在于给定的不是连续范围,是离散的值
p0 : 1,2,3
p1 : 11,12,13
p2 : 17,18,19
3.HASH分区:根据用户自定义的表达式的返回值进行分区,返回值不能是负数
指定好有几个区块,即可通过linear Rhash的方式进行分区.
而分区的字段可以使用表达式,比如id*10
4.KEY分区:根据MySQL内部提供的哈希函数进行分区
和hash分区类似,不过不允许使用自定义表达式,只能填写字段,比如id
KEY分区使用系统提供的HASH函数进行分区
5.COLUMNS分区:5.5开始支持,可以直接使用非整形的数据进行分区,分区根据类型直接比较而得,不需要转换为整形
可以有非整数和多列进行分区.
二:优势
容量:对于单表来说,硬盘容量增加了许多,因为是可扩容的.
删除:由于删除某个分区时,会连带数据一起删除,当需要删除老数据或者其他数据时,
如果当时分区是按照对应的规则进行分区,则可直接删除对应分区,会比delete快得多.
查询:通过特定的条件查询,读取会走到具体的分区数据,由于数据体积减少,从而大大的提高了查询效率.
吞吐量:分区表数据通过分片的方式还可以分布在不同的物理设备上,从而高效利用多种硬件设备,来提高吞吐量.
迁移:可备份和恢复单个分区
三:分区分片的场景
分区不支持跨机器,当需要跨机器时需要结合分片.
四:分区分片与分库分表相比
分区优点:
1.实现上分区分片上较为容易.在只需要分区时,无需改动应用层.
分区缺点:
1.第一次访问一个分区表时,MySQL需要把所有分区都访问一遍
2.在server层,认为这是同一张表,因此所有分区共用同一MDL锁,在发生DDL操作时,可能会发生锁表.
3.对于mysql有一定限制,比如最大分区数目不能超过1024,如果含有唯一索引或主键,那么分区列就必须包含起来等.
4.不可控,在熟练度不高的情况下,更难定位到问题
选择场景:
一般情况下都是不建议使用分区的,除非还没有成熟的分库分表中间件或者数据增长还不算太快且都是以一个区块范围查询的则可以使用分区.
Newsql
NewSql有Vitess、CockroachDB、TiDB、ClustrixDB、MemSQL、NuoDB、Altibase、VoltDB、Citus等等
这里就以TiDB为例进行说明
一: HTAP
在说HTAP之前,需要大致的先了解一下OLTP、OLAP
OLTP:事务型,实时性要求高,比如日常的增删改查,一套转账流程,需要在段时间内到账.(数量一般都不会特别大)
OLAP:分析型,实时性要求不高,一般可以以天为单位,但数据量较大,查询一般都是动态,需要支持复杂的分析操作.
HTAP:既支持实时事物,也支持大批量数据分析.
使用存储方案来处理这些场景.
行存储:
行存储方案适用于OLTP,行存储就相当于我们现在使用的mysql,是以一行一行为单位进行存储的,
优点:因为对应的行属于元数据,当数据新增删除修改时会非常的快,能间接的达到实时的效果.
缺点:当使用几个属性查询时,却需要便利一整条完整的行数据,从而使读取数据大大降低.
对此,数据库给的解决方案是"索引",但建立索引需要花费大量的时间和资源.
列存储:
列存储方案适用于OLAP,比如目前的HBase,是以一列一列的单位进行存储,
优点:由于每列都是元数据,间接性的相当于每列都是索引,可以有效的通过指定的属性进行查询.在返回对应的整体数据,大大的提高了查询性能
缺点:由于是列存储,使用删除或跟新时,需要找到对应数据才能做调整,导致在这方面性能下降.
表中列属性比较少时,意义也会不大。
行+列存储(TiDB HTAP):
HTAP存储引擎:行和列存储同时存在,行来处理事务的实时性,列来处理数据的分析.
HTAP数据一致性:使用raft协议来保证多副本的一致性和高可用.
HTAP数据隔离性:TiKV、TiFlash可以分别部署到不同的机器。
二: TiDB架构
主要分为三个组件
TiDB Server
1.接收到sql之后,处理sql相关的逻辑,并通过PD找到TiKV的数据,本身只负责计算,不负责存储
PD Server
1.元数据的存储,例如属性对应存放TiKV的位置.
2.TiKV的调度,调度维度是region
3.全局事务id的分配.
4.本身有
TiKV Server
1.存放数据,以region为单位,每个region默认都会有三个副本,以便容灾使用.
2.每个节点和pd之间存在心跳的关系,用来确认节点是否还活着或是否有新加入的节点,另外一方面,心跳也会自带一些节点信息,比如总磁盘,可用磁盘量等.
3.数据间的同步和可用性使用的是Raft来保证.
三: 优缺点
优点:
1.水平拓展:存储(tikv)和计算(tidb),存储和计算可以独立进行拓,当其中一个资源不够时,可直接添加机器.
2.高度兼容mysql语法,可以直接迁移数据。
3.事物的强一致性.
4.支持HTAP,既支持实时事物,也支持大批量数据分析
缺点:
1.对于mysql的特性和行为并不是完全支持
2.在数据量不大的情况下,没有什么意义.
四:于mysql相比
如果从实现上来说其实mysql都能实现tidb的效果,只不过很麻烦,所以就从应用场景来说.
在数据量特别大且增量数据无法确定的情况下还需要保证事物的强一致性,建议就选tidb了.
在选型的时候,还是要考虑下场景和熟练度,目前来说mysql比tidb还是成熟很多,当遇到问题时,解决起来,各种渠道到能帮助你快速解决mysql问题,tidb相对于mysql就没那么完善了.