mysql分库分表
一、整体的切分方式
1、分库分表:即数据的切分就是通过某种特定的条件,将我们存放在同一个数据库中的数据分散存放到多个数据库(主机)中,以达到分散单台设备负载的效果
2、数据的切分根据其切分规则的类型,可以分为如下两种切分模式
【1】垂直(纵向)切分:把单一的表拆分成多个表 / 将不相关的表,分散到不同的数据库(主机)上。
如:用户表、商品SKU表、交易Pay表,根据业务不同进行切分,将表切分到不同数据库上。
优点:
(1)。拆分后业务清晰,拆分规则明确
(2)。系统之间进行整合或扩展很容易
(3)。按照成本、应用的等级、应用的类型等将表放到不同的机器上,便于管理
(4)。便于实现动静分离、冷热分离的数据库表的设计模式
冷热分离:冷数据(查询多,变化少),热数据/活跃数据(变化多)。将冷热数据分开存放即冷热分离。
(5)。数据维护简单
缺点:
(1)。部分业务表无法关联(Join),只能通过接口方式解决,提高了系统的复杂度
(2)。受每种业务的不同限制,存在单库性能瓶颈,不易进行数据扩展和提升性能
(3)。事务处理复杂
设计数据库表结构时考虑因素:
(1)。冷数据适合MyISAM存储引擎(查询快) ,热数据适合InnoDB存储引擎(更新快)。
(2)。主从分离:主库用于写入操作,从库(可配置更多从库)用于查询操作,分担请求压力。
(3)。针对活跃/热数据,可采用Memcache、Redis等缓存,待累计一定量时再更新DB。
【2】水平(横向)切分:根据表中数据的逻辑关系,将同一个表中的数据按照某种条件拆分到多台数据库(主机)上。
如:用户表可根据ID被水平切分为用户1表 & 用户2表 (表结构一致),即用户表数据=用户1表数据+用户2表数据
优点:
(1)。单库单表的数据保持在一定的量级,有助于性能的提高。
(2)。切分的表的结构相同,应用层改造较少,只需要增加路由规则即可。
(3)。提高了系统的稳定性和负载能力。
缺点:
(1)。切分后,数据是分散的,很难利用数据库的Join操作,跨库Join性能较差
(2)。拆分规则难以抽象。
(3)。分片事务的一致性难以解决。
(4)。数据扩容的难度和维护量极大。
以上,水平/垂直切分共同点:
- 存在分布式事务的问题。
- 存在跨节点Join的问题。
- 存在跨节点合并排序、分页的问题。
- 存在多数据源管理的问题。
二、水平切分方式的路由过程和分片维度
1. 水平切分的路由过程
我们在设计表时需要确定对表按照什么样的规则进行分库分表。
例如,当有新用户时,程序得确定
(1)。将此用户的信息添加到哪个表中;
(2)。在登录时我们需要通过用户的账号找到数据库中对应的记录。
所有这些都需要按照某一规则进行路由请求,因为请求所需要的数据分布在不同的分片表中。
以上:针对输入的请求,通过分库分表规则查找到对应的表和库的过程叫作路由。
例如:
分库分表的规则是user_id % 4,当用户新注册了一个账号时,假设用户的ID是123,我们就可以通过123 % 4 = 3确定此账号应该被保存在User3表中。
当ID为123的用户登录时,我们可通过123 % 4 = 3计算后,确定其被记录在User3中。
2. 水平切分的分片维度(可参考Myca提供的切片方式)
【1】按照哈希切片
哈希分片:对数据的某个字段求哈希,再除以分片总数后取模,取模后相同的数据为一个分片。
按照哈希分片常常应用于数据没有时效性的情况,比如所有数据无论是在什么时间产生的,都需要进行处理或者查询。
优点:数据切片比较均匀,对数据压力分散的效果较好。
缺点:数据分散后,对于查询需求需要进行聚合处理。
【2】按照时间切片
时间分片:按照时间的范围将数据分布到不同的分片上。(这种切片方式适用于有明显时间特点的数据)
三、分片后的事务处理机制
(一)、分布式事务
由于我们将单表的数据切片后存储在多个数据库甚至多个数据库实例中,所以依靠数据库本身的事务机制不能满足所有场景的需要。
但是,我们推荐在一个数据库实例中的操作尽可能使用本地事务来保证一致性,跨数据库实例的一系列更新操作需要根据事务路由在不同的数据源中完成,各个数据源之间的更新操作需要通过分布式事务处理。
主流的分布式事务解决方案有三种:两阶段提交协议、最大努力保证模式和事务补偿机制。
1、两阶段提交协议
两阶段提交协议将分布式事务分为两个阶段,一个是准备阶段,一个是提交阶段,两个阶段都由事务管理器发起。
基于两阶段提交协议,事务管理器能够最大限度地保证跨数据库操作的事务的原子性,是分布式系统环境下最严格的事务实现方法。
符合J2EE规范的AppServer(例如:Websphere、Weblogic、Jboss等)对关系型数据库数据源和消息队列都实现了两阶段提交协议,只需在使用时配置即可
如图所示:
但是,两阶段提交协议也带来了性能方面的问题,难于进行水平伸缩,因为在提交事务的过程中,事务管理器需要和每个参与者进行准备和提交的操作的协调,在准备阶段锁定资源,在提交阶段消费资源。
但是由于参与者较多,锁定资源和消费资源之间的时间差被拉长,导致响应速度较慢,在此期间产生死锁或者不确定结果的可能性较大。因此,在互联网行业里,为了追求性能的提升,很少使用两阶段提交协议。
另外,由于两阶段提交协议是阻塞协议,在极端情况下不能快速响应请求方,因此有人提出了三阶段提交协议,解决了两阶段提交协议的阻塞问题,但仍然需要事务管理器在参与者之间协调,才能完成一个分布式事务。
2、最大努力保证模式
这是一种非常通用的保证分布式一致性的模式,很多开发人员一直在使用,但是并未意识到这是一种模式。最大努力保证模式适用于对一致性要求并不十分严格但是对性能要求较高的场景。
具体的实现方法是,在更新多个资源时,将多个资源的提交尽量延后到最后一刻处理,这样的话,如果业务流程出现问题,则所有的资源更新都可以回滚,事务仍然保持一致。
唯一可能出现问题的情况是在提交多个资源时发生了系统问题,比如网络问题等,但是这种情况是非常罕见的,一旦出现这种情况,就需要进行实时补偿,将已提交的事务进行回滚,这和我们常说的TCC模式有些类似。
下面是使用最大努力保证模式的一个样例,在该样例中涉及两个操作,一个是从消息队列消费消息,一个是更新数据库,需要保证分布式的一致性。
(1)开始消息事务。
(2)开始数据库事务。
(3)接收消息。
(4)更新数据库。
(5)提交数据库事务。
(6)提交消息事务。
这时,从第1步到第4步并不是很关键,关键的是第5步和第6步,需要将其放在最后一起提交,尽最大努力保证前面的业务处理的一致性。
到了第5步和第6步,业务逻辑处理完成,这时只可能发生系统错误,如果第5步失败,则可以将消息队列和数据库事务全部回滚,保持一致。如果第5步成功,第6步遇到了网络超时等问题,则这是唯一可能产生问题的情况。
在这种情况下,消息的消费过程并没有被提交到消息队列,消息队列可能会重新发送消息给其他消息处理服务,这会导致消息被重复消费,但是可以通过幂等处理来保证消除重复消息带来的影响。
当然,在使用这种模式时,我们要充分考虑每个资源的提交顺序。我们在生产实践中遇到的一种反模式,就是在数据库事务中嵌套远程调用,而且远程调用是耗时任务,导致数据库事务被拉长,最后拖垮数据库。
因此,上面的案例涉及的是消息事务嵌套数据库事务,在这里必须进行充分评估和设计,才可以规避事务风险。
3、事务补偿机制
显然,在对性能要求很高的场景中,两阶段提交协议并不是一种好方案,最大努力保证模式也会使多个分布式操作互相嵌套,有可能互相影响。这里,我们给出事务补偿机制,其性能很高,并且能够尽最大可能地保证事务的最终一致性。
在数据库分库分表后,如果涉及的多个更新操作在某一个数据库范围内完成,则可以使用数据库内的本地事务保证一致性;对于跨库的多个操作,可通过补偿和重试,使其在一定的时间窗口内完成操作,这样就可以实现事务的最终一致性,突破事务遇到问题就滚回的传统思路。
如果采用事务补偿机制,则在遇到问题时,我们需要记录遇到问题的环境、信息、步骤、状态等,后续通过重试机制使其达到最终一致性,详细内容可以参考《分布式服务架构:原理、设计与实战》第2章,彻底理解ACID原理、CAP理论、BASE原理、最终一致性模式等内容。
本文来自于:
https://www.toutiao.com/a6545626478447428103/?tt_from=weixin&utm_campaign=client_share&article_category=stock×tamp=1524215325&app=news_article&utm_source=weixin&iid=28070358035&utm_medium=toutiao_android&wxshare_count=1
原文地址:https://www.cnblogs.com/kaixinyufeng/p/8892684.html