分库分表那些事

问题1: 分库解决什么问题

  • 单实例容量有限,能容纳数据量是有限的
  • 单实例能接受的连接数(请求数)有限,
  • 超过限度都会报错

问题2: 分表解决什么问题

  • 查询慢: 大表数据多,每次查询需要更多次 io
  • 写入慢: 数据越多,写入索引的平衡越复杂,速度越慢

问题3: 有哪些分法?

垂直
  • 按业务拆分

例子:

  • 分库: 将一个有"电商库"分成"用户库",商品库,订单库等…
  • 分表: “商品表"有 50 个字段,按业务可以分成"商品基本信息表”(名称,品类什么的)与"商品拓展信息表"(详情描述什么的)

问题4 : 数据一致性

如果你的数据在不同的数据库,如何保证数据一致性.

例子: 现在分成了"用户库",商品库,订单库三个库

现在买一个东西要

  1. 扣除用户的余额
  2. 扣除商品库存
  3. 记录订单信息

如何保证他们的一致?

解决方法 1: 强一致性 - XA 分布式事务(双写/两阶段提交)
  • 先开始事务并更新(持有数据的所有资源)
  • 等待所有任务全部成功了再一起进行提交,释放资源

例子:

  • 提交购买请求
  • 所有库(用户,商品,订单)都开启一个事务,写数据
  • 写好后方法一个 ok 的状态
  • 等所有接口都 ok 了再一起提交
    (如何判断所有都 ok 了?,那如果一起提交的时候有数据库没提交成功有的成功怎么办?如何回滚?)
解决方法2 : 最终一致性
ⅰ. 每个任务分别执行(各跑各的)
ⅱ. 最终结果检查与补偿(如果有失败的:回滚;如果没有:正常成功),只保证最终结果的一致性

c. 消息队列 MQ如何实现最终一致性
ⅰ. 确认机制: 确保每个任务都执行成功
ⅱ. 重试机制: 确保每个任务都能够收到,没收到就会重试

ⅲ. 让你设计如何做?

  1. 比如一个购物功能(记录订单,扣商品库存,扣用户余额)
  2. 首先扣除库存(使用接口,如果失败说明库存不足)就返回库存不足
  3. 生成订单唯一 id(避免重复消费),并记录订单状态为处理中(如果失败就将状态设置成失败,否则就设置成成功)
  4. 发送消息给扣除用户余额的队列,
    a. 如果超时就继续尝试,如果多次尝试(3 次就进行报警,通知管理员维护)
    b. 如果成功就发送成功信息到消息队列(订单服务读取信息并设置成对应的状态)
    c. 如果失败就同时发送失败的信息分别给订单与库存,(库存进行补偿,将减掉的库存加回来)
消息队列如何保证只消费了一次?(重复消费问题)

产生原因:消息队列的重试机制

  1. 全局 id,需要开发者维护全局 id(MySQL/redis)
  2. 每次消费前先检查是否消费过,如果消费过就不再重复消费
微服务(rpc)是如何保证幂等性性的?如何保证只请求了一次?
  1. 唯一请求的标记( token 存活时间:超时前)
  2. 接受请求先检查 token 是否存在,如果存在就不再处理,如果不存在就记录 token,再进行处理
  3. 客户端发送请求将再一段时间没有收到返回的情况下进行重试(相同的 token),直到 token 过期超时
水平

根据分片键进行

  1. 范围分片
  2. 哈希分片

问题 5: 如何解决数据查询的问题

例子:

  • 如果你使用的用户名(用户 id)进行分片,你想查询某个时间段的数据岂不是要跑到所有分片中查询一遍,再将结果汇总,
  • 如果有1000 个分片,那么查询一次的消耗就变成了 1000 次.

所以分片键的选择很重要,要尽量让查询不要分散到所有库中

问题6: 如何解决数据的均衡问题?

MongoDB 如何实现数据均衡的?
  • MongoDB有数据块的概念
  • 块的分裂: 当块达到容量的限度就会自动的分裂,将数据平均分成两份
  • 块的迁移(均衡): 中心节点会根据每个分片的数据块的数量,将数据块多的分片的一些数据块迁移到数据块少的分片,并对应的更新他们的查询数据时指向的分片.
扩容
  • 分片的增加也是通过这套逻辑进行数据的迁移与平衡的
redis Cluster如何实现数据均衡的?
  • redis Cluster会根据节点的数量分配哈希槽,每个分片所持有的数据差距不大(理解为均衡的)
扩容
  • redis Cluster扩容(或者节点减少,会重新分配哈希槽)
  • 扩容就是每个现在的节点都拿出一部分哈希槽给新的节点,实现哈希槽的均衡(数据的均衡)
  • 节点减少就会每个节点平均分配减少节点持有的槽

扩容过程:

  1. 哈希槽重新分配,新节点会从每个节点获取一些哈希槽,实现哈希槽的均衡
  2. 数据迁移: 旧的节点会将不属于自己的数据(被获取的槽)迁移到新的节点.

参考:
https://blog.youkuaiyun.com/java_2017_csdn/article/details/134329288
https://cloud.tencent.com/developer/article/2181007
https://cn.pingcap.com/article/post/8525.html
https://developer.aliyun.com/article/1199962

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值