分库分表中的问题
分布式事务问题
==待整理==
全局唯一 ID 的生成
雪花模型算法
通过雪花模型服务生成唯一 ID。
mysql自增初始值与步长
通过 mysql 的 auto increment,从 mysql 取 ID。
为避免单点故障,用多台 mysql 服务器,每台 mysql 服务器上放一个自增的 sequence 表,自增的步长就是自增服务器的数量,sequence 表的起始值分别是 1,2…N。
缺点是要两台以上 mysql,废资源。
自己写编码规则
自己写的编码规则不仅能尽量保证唯一性,还能携带业务规则,方便逻辑判断。
一般自己写的唯一 ID 都会包括三部分:时间戳 + 随机数 + 某个编码。
其中时间戳用来区分数据的冷热;某个编码可以是某个业务编码,比如用户编码、服务器编码、地域编码等等,这个业务编码也用来区分数据;随机数必须使用高唯一性随机码。
缺点是规则设计比较难,要充分考虑业务情况。另外,由于使用了随机数,是有可能存在着 ID 重复的可能性的,所以要有容错机制,即如果插入的时候 ID 重复,那么重新生成再插入。
排序、分组、分页问题
==待整理==
读写分离主从库数据不一致问题
问题出现原因
往主库写数据以后,从库还没来得及从主库复制数据,读请求就已经发到从库了,这时从库的数据就不是最新的,查到的就不是新数据;
解决办法
配置主库的复制策略为半同步复制,必须有一个 slave 节点接收到主库复制的数据,主库才认定这条 SQL 执行成功;
跨库 Join 的问题
问题出现原因
分库分表以后,数据处于不同的库里,这个时候需要做关联查询
解决办法
1)首先,对于这类问题,我们的首要方案是尽力避免跨库 Join,避免的方式包括:
- 采用 mycat 全局表,比如数据字典,在每个库里都需要用到,那我们在每个库里都放一份,然后做成全局表进行同步,这样库表跟数据字典的 join 就不会跨库了;
- 采用字段冗余,比如 ID 和 NAME,表里只有 ID,没有 NAME,NAME 在另一个库里,那我们在设计之初就在表里也加上 NAME,这样就不用会查另一个库的表了。不过这样有个问题,就是数据不一致的问题,需要定期更新这部分数据;
- 在业务上进行划分,对于需要关联的表放在一个库下面(不可能所有的表都需要关联,那肯定有问题重新设计吧),其他的可以采用服务的方式对外提供接口方便调用查询数据。
2)其次,如果已经出现了这种情况,那解决方式有:
- mycat 中配置表的 childtable,作为它的从表,并设置 joinKey,这样从表的数据也会跟主表存在一个库里面;
- 手工查询,先主库查出来,然后一条一条从从库查,这样性能比较低。不过可以对从库的数据查询加缓存,能提高效率。
线上环境分库分表后的迁移
采用双写的方式,修改代码,所有涉及到分库分表的表的增、删、改的代码,都要对新库进行增删改。
同时,再有一个数据抽取服务,不断地从老库抽数据,往新库写,边写边按时间比较数据是不是最新的。
原文/引用
本文是原创文章,采用 CC BY-NC-ND 4.0 协议,完整转载请注明来自 程序员小航
评论
匿名评论
隐私政策
你无需删除空行,直接评论以获取最佳展示效果