最近了解了一下分库分表,看完之后的感悟就是,能不用就不用!!一用就会有超多问题,果然每个技术不仅有优点而且背后都是有超级大的成本的,接下来我就来分享一下分库分表。
在镇安等地区,都构建了全面的区域性战略布局,加强发展的系统性、市场前瞻性、产品创新能力,以专注、极致的服务理念,为客户提供
网站设计制作、网站设计 网站设计制作按需定制,公司网站建设,企业网站建设,
品牌网站设计,
成都营销网站建设,外贸营销网站建设,镇安网站建设费用合理。数据库分库分表后带来的优点和缺点
分库分表解决的现状问题
- 连接数: 连接数过多时,就会出现‘too many connections’的错误,访问量太大或者数据库设置的大连接数太小的原因
- Mysql默认的大连接数为100.可以修改,而mysql服务允 许的大连接数为16384
- 数据库分表可以解决单表海量数据的查询性能问题
- 数据库分库可以解决单台数据库的并发访问压力问题
- 解决系统本身IO、CPU瓶颈
- 磁盘读写IO瓶颈,热点数据太多,尽管使用了数据库本身缓存,但是依旧有大量IO,导致sql执行速度慢
- 网络IO瓶颈,请求的数据太多,数据传输大,网络带宽不够,链路响应时间变⻓
- CPU瓶颈,尤其在基础数据量大单机复杂SQL计算,SQL语 句执行占用CPU使用率高,也有扫描行数大、锁冲突、锁等待等原因
分库分表带来新的问题
- 数据库切分前,多表关联查询,可以通过sql join进行实现
- 分库分表后,数据可能分布在不同的节点上,sql join带来 的问题就比较麻烦
- 不同维度查看数据,利用的partitionKey是不一样的
- 订单表 的partionKey是user_id,用户查看自己的订单列表方便
- 但商家查看自己店铺的订单列表就麻烦,分布在不同数据节
- 问题二:分库操作带来的分布式事务问题
- 操作内容同时分布在不同库中,不可避免会带来跨库事务
- 问题三,即分布式事务 问题三:执行的SQL排序、翻⻚、函数计算问题
- 分库后,数据分布再不同的节点上, 跨节点多库进行查询时,会出现limit分⻚、order by排序等问题
- 而且当排序字段非分片字段时,更加复杂了,要在不同的分片节点中将数据进行排序并返回,然后将不同分片返回的结果集进行汇总和再次排序(也会带来更多的CPU/IO资 源损耗)
- 常规表的id是使用自增id进行实现,分库分表后,由于表中数据同时存在不同数据库中,如果用自增id,则会出现冲突问题
- 业务发展快,初次分库分表后,满足不了数据存储,导致需要多次扩容
OK!相信大家看完这么多问题,头都快大了叭,咱们先轻松一下,看看啥是分库分表
【垂直分表-垂直分库】
- 需求:商品表字段太多,每个字段访问频次不一样,浪费了IO资 源,需要进行优化
- 垂直分表介绍
- 也就是“大表拆小表”,基于列字段进行的
- 拆分原则一般是表中的字段较多,将不常用的或者数据较大,⻓度较⻓的拆分到“扩展表 如text类型字段
- 访问频次低、字段大的商品描述信息单独存放在一张表中;
- 访问频次较高的商品基本信息单独放在一张表中
- 垂直拆分原则
- 把不常用的字段单独放在一张表;
- 把text,blob等大字段拆分出来放在附表中;
- 业务经常组合查询的列放在一张表中
- 需求:C端项目里面,单个数据库的CPU、内存⻓期处于90%+的 利用率,数据库连接经常不够,需要进行优化
- 垂直分库讲解
- 垂直分库针对的是一个系统中的不同业务进行拆分, 数据库 的连接资源比较宝贵且单机处理能力也有限
- 没拆分之前全部都是落到单一的库上的,单库处理能力成为瓶 颈,还有磁盘空间,内存等限制
- 拆分之后,避免不同库竞争同一个物理机的CPU、内存、网络 IO、磁盘,所以在高并发场景下,垂直分库一定程度上能够 突破IO、连接数及单机硬件资源的瓶颈
- 垂直分库可以更好解决业务层面的耦合,业务清晰,且方便管理和维护
- 一般从单体项目升级改造为微服务项目,就是垂直分库
【水平分表-水平分库】
- 需求:当一张表的数据达到几千万时,查询一次所花的时间⻓, 需要进行优化,缩短查询时间
- 都是大表拆小表
- 把一个表的数据分到一个数据库的多张表中,每个表只有这个 表的部分数据
- 核心是把一个大表,分割N个小表,每个表的结构是一样的, 数据不一样,全部表的数据合起来就是全部数据
- 针对数据巨大的单张表(比如订单表),按照某种规则 (RANGE,HASH取模等),切分到多张表里面去 但是这些表还是在同一个库中,所以单数据库操作还是有IO 瓶颈,主要是解决单表数据量过大的问题
- 减少锁表时间,没分表前,如果是DDL(create/alter/add等) 语句,当需要添加一列的时候mysql会锁表,期间所有的读写 操作只能等待
- 需求:高并发的项目中,水平分表后依旧在单个库上面,1个数 据库资源瓶颈 CPU/内存/带宽等限制导致响应慢,需要进行优化
- 水平分库
- 把同个表的数据按照一定规则分到不同的数据库中,数据库在不同的服务器上
- 水平分库是把不同表拆到不同数据库中,它是对数据行的拆分,不影响表结构
- 每个库的结构都一样,但每个库的数据都不一样,没有交集, 所有库的并集就是全量数据
- 水平分库的粒度,比水平分表更大
好!看完了基础的啥是分库分表,咱要直面狂风暴雨了,首当其冲的就是,当使用了用户的uiserId当成PartitionKey分库分表后,用户想要查看订单列表非常简单,只需要用自己的用户id取模一下,就能找到所有的订单是哪个库,那个表,但是,可怜的商家呢,他完全没法知道所有买了他辛辛苦苦卖出去商品的用户ID,那么他用啥来取模,找到自己卖出去的商品订单呢!
解决方式一【NONOSQL方案】
- 订单表 的partionKey是user_id,用户查看自己的订单列表方便
- 订单数据在ES上冗余一份,让商家去ES查
解决方式二【冗余双写方案】
- 既然!一个partionKey满足不了需求,那么非常简单,直接整两个partionKey
- 拆分买家库和卖家库
- 买家库,按照用户的id来分库分表
- 卖家库,按照卖家的id来分库分表
OK!这两种方案一出来,看起来冗余双写方案会更好一点,但是其实还是要看业务,哈哈哈哈哈,冗余双写的方案没有过多的中间件节点,越少!系统越稳定,而且ES太吃内存啦,要好多钱钱。不过选择具体的技术方案的时候一定要结合业务哦。
方案敲定了,那么随之而来的又是一个大问题,分布式的事务咋解决???
好~在说解决方案之前,老规矩,啥是分布式事务呢,为啥就会有分布式事务的问题嘞?
什么是分布式事务
- 事务指的就是一个操作单元,在这个操作单元中的所有操作最终要保持一致的行为,要么所有操作都成功,要么所有的操作都被撤销
- 一个是本地事务:
- 本地事物其实可以认为是数据库提供的事务机
- 一个是分布式事务
- 分布式事务指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上。简单的说,就是一次大的操作由不同的小操作组成,这些小的操作分布在不同的服务器上,且属于不同的应用分布式事务需要保证这些小操作要么全部成功,要么全部失败。
- 本质上来说,分布式事务就是为了保证不同数据库的数据一致性
- 产生的原因 业务发展,数据库的拆分-分库分表 SOA和微服务架构的使用
- 多个微服务之间调用异常
分布式事务下数据最终一致性-CAP的权衡 结果 BASE理论
- CAP 中的一致性和可用性进行一个权衡的结果,核心思想就是: 我们无法做到强一致,但每个应用都可以根据自身的业务特点, 采用适当的方式来使系统达到最终一致性, 来自 ebay 的架构 师提出
- Basically Available(基本可用)
- 假设系统,出现了不可预知的故障,但还是能用, 可能 会有性能或者功能上的影响,比如RT是10ms,变成 50ms
- 允许系统中的数据存在中间状态,并认为该状态不影响系统的整体可用性,即允许系统在多个不同节点的数据副本存在数据延时
- Eventually consistent(最终一致性)
- 系统能够保证在没有其他新的更新操作的情况下,数据最终一定能够达到一致的状态,因此所有客户端对系统的数据访问最终都能够获取到最新的值
- 关于数据一致性
- 强一致:操作后的能立⻢一致且可以访问
- 弱一致:容忍部分或者全部访问不到
- 最终一致:弱一致性经过多一段时间后,都一致且正常
分布式事务的常⻅解决方案
刚性事务模型
在分布式系统中,每一个机器节点能够明确知道自己在进行事务 操作过程中的 结果是成功还是失败,但无法直接获取到其他分 布式节点的操作结果
当一个事务操作跨越多个分布式节点的时候,为了保持事务处理 的 ACID 特性,
需要引入一个“协调者”(TM)来统一调度所有分布式节点的执行 逻辑,这些被调度的分布式节点被称为 AP。
TM 负责调度 AP 的行为,并最终决定这些 AP 是否要把事务 真正进行提交到(RM)
两阶段提交 2PC流程解析
- 事务管理器给每个参与者都发送Prepared消息,每个数 据库参与者在本地执行事务,并写本地的Undo/Redo日 志,此时事务没有提交。
- Undo日志是记录修改前的数据,用于数据库回滚
- Redo日志是记录修改后的数据,用于提交事务后写入数据
- 如果事务管理器收到了参与者的执行失败或者超时 消息时,直接给每个参与者发送回滚(Rollback)消 息,否则发送提交(Commit)消息;
- 参与者根据事务管理器的指令执行【提交】或者 【回滚】操作,并释放事务处理过程中使用的锁资源
刚性事务总结
- XA协议简单,数据库支持XA协议,开发使用成本比较低
- 对业务侵入很小,大的优势就是对使用方透明
- 用户可以像使用本地事务一样使用基于 XA 协议的分布式事务,能够严格保障事务ACID 特性
- 事务执行过程中需要将所需资源全部锁定,也就是俗称的刚性事务
- 性能不理想,占用锁资源比较多,高并发常⻅下无法满足
柔性事务模型
- 刚性事务:遵循ACID
- 柔性事务:遵循BASE理论
- TCC:
- Try:完成所有业务检查( 一致性 ) ,预留必须业 务资源( 准隔离性 )
- Confirm :对业务系统做确认提交,默认 Confirm阶段不会出错的 即只要Try成功, Confirm一定成功
- Cancel : 业务执行错误,需要回滚的状态下执行的业务取消,预留资源释放, 进行补偿性
- TCC 事务和 2PC 的类似,Try为第一阶段,Confirm - Cancel为第二阶段,它对事务的提交/回滚是通过 执行一段 confirm/cancel 业务逻辑来实现,并且也 并没有全局事务来把控整个事务逻辑
柔性事务总结
- 它把事务运行过程分成 Try、Confirm/Cancel 两个阶段
- 每个阶段由业务代码控制,这样事务的锁力度可以完全自由控制
- 不存在资源阻塞的问题,每个方法都直接进行事务的提交
- 在业务层编写代码实现的两阶段提交,原本一个方法, 现在却需要三个方法来支持
- 对业务的侵入性很强,不能很好的复用
- 注意:使用TCC时要注意Try - Confirm - Cancel 3个操作的幂等控制,由于网络原因或者重试操作都有可能导致这 几个操作的重复执行
事务消息
- 消息队列提供类似Open XA的分布式事务功能,通过消 息队列事务消息能达到分布式事务的最终一致
- 暂不能投递的消息,发送方已经成功地将消息发送到了 消息队列服务端,但是服务端未收到生产者对该消息的 二次确认,此时该消息被标记成“暂不能投递”状态,处 于该种状态下的消息即半事务消息。
- 由于网络闪断、生产者应用重启等原因,导致某条事务 消息的二次确认丢失,消息队列服务端通过扫描发现某 条消息⻓期处于“半事务消息”时,需要主动向消息生产 者询问该消息的最终状态(Commit或是Rollback), 该询问过程即消息回查
事务消息总结
- 事务消息不仅可以实现应用之间的解耦,又能保证数据的最终一致性
- 同时将传统的大事务可以被拆分为小事务,能提升效率
- 不会因为某一个关联应用的不可用导致整体回滚,从而大限度保证核心系统的可用性
- 不能实时保证数据一致性
- 极端情况下需要人工补偿,比如 假如生产者成功处理本 地业务,消费者始终消费不成功
总结
OK!了解完分布式事务,在看看双写的模型,多么妙啊,这里的消息队列不仅可以选择事务消息来处理分布式事务的问题,甚至自己想再让事务锁的粒度小一点的话,可以自己写柔性事务,比如提交订单的时候发一个消息,没有异常之后,状态机推进到最后一个状态,再提交事务。
OMG!我只是解决两个问题,就扯出来这么多,别说还有主键ID如何确保不重复,数据存到数据库里,会不会有些数据库读写特别频繁,有些数据库没啥读写量嘞,分库分表完发现还是不够用,需要再分库分表一次,那么这个时候,如何保障以前的数据不用迁移呢,这些问题还是等以后的我继续补充叭(挖坑.jpg)。
你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧
网页名称:分库分表太坑啦!-创新互联
网页网址:
http://bjjierui.cn/article/joohi.html