84669 人学习
152542 人学习
20005 人学习
5487 人学习
7821 人学习
359900 人学习
3350 人学习
180660 人学习
48569 人学习
18603 人学习
40936 人学习
1549 人学习
1183 人学习
32909 人学习
当单表的数据量过大时,会采用MySQL进行水平拆分,请问原先的自动增长的ID有什么好的解决办法?
人生最曼妙的风景,竟是内心的淡定与从容!
水平拆分后,同一张表的数据放在不同的库上,无法再依赖数据库本身的auto_increment实现ID的唯一性,多个库之间产生的ID会造成冲突。因此ID不应该由数据库来分配,那么应该由什么来分配,我觉得要分两种情况:
如果应用是通过数据库中间件来访问后台的MySQL,那么ID应该由中间件来生成
如果没有中间件,ID由应用生成
但无论是应用还是中间件,应用肯定会是多个的(多个客户端),而中间件,中间件一般也不会部署一个单实例,这样会有单点问题(single point of failure), 中间件在生产环境下,是集群部署的。
那么问题就清晰明了得多了,无论是上面哪一种情况,实际上你需要的是一个全局的,global的ID生成器。
全局的global生成器有很多种方式可以实现
从公共数据库取ID
把ID生成策略放在zookeeper集群上,去zookeeper集群上取全局ID
基本的策略就是这样了。还有一点小细节。
全局ID最好以表来划分,一个表对应一个全局ID上下文,不同的表去不同的全局ID上下文取。
另外一个,无论是中间件也好,应用也好,取全局ID时不要每次只取一个,那样性能太低了,更好的方式是每次取一段ID,比如应用1取到了1-50这段ID,那么它就可以在这50个ID用完之前,不再需要去取ID;应用2也去取ID,那么它会取到51-100这段ID,这个思想有点像储存食物过冬一样。
目前我这已知的方法:1.修改原有的自增列,变为不自增主键。自己维护主键
2.水平拆分为拆分已有数据,也就是说拆分出去的表的数据不会再做变化。新增的数据依然自增。(注意不能设置自增填充空白id)
3.做个统一算法。自增id需要计算后写入,而不是自动维护
我这边之前也有这样的需求。我是这么处理的:把主键列去掉自增长,通过redis的incr产生自增序列值,插入的时候指定id的值
1.把自增ID这个功能,用一张表与一个存储过程做成一个小模块。
2.被拆分的表,当有数据INSERT时,就调用这个存储过程来申请一个新ID。
分表后主键要自己生成最好,很多开源的主键生成策略算法,比如说twitter的snowflake等如果不想改动程序的话,设置每个集群中自增 ID 起始点(auto_increment_offset)以及 ID 自增步长(auto_increment_increment),让目前每个集群的起始点错开,达到将 ID 相对分段的效果来满足全局唯一的效果。优点是实现简单,对应用透明,缺点就是,以后如果根据id做路由的话不好扩展
水平拆分后,同一张表的数据放在不同的库上,无法再依赖数据库本身的auto_increment实现ID的唯一性,多个库之间产生的ID会造成冲突。
因此ID不应该由数据库来分配,那么应该由什么来分配,我觉得要分两种情况:
如果应用是通过数据库中间件来访问后台的MySQL,那么ID应该由中间件来生成
如果没有中间件,ID由应用生成
但无论是应用还是中间件,应用肯定会是多个的(多个客户端),而中间件,中间件一般也不会部署一个单实例,这样会有单点问题(single point of failure), 中间件在生产环境下,是集群部署的。
那么问题就清晰明了得多了,无论是上面哪一种情况,实际上你需要的是一个全局的,global的ID生成器。
全局的global生成器有很多种方式可以实现
从公共数据库取ID
把ID生成策略放在zookeeper集群上,去zookeeper集群上取全局ID
基本的策略就是这样了。还有一点小细节。
全局ID最好以表来划分,一个表对应一个全局ID上下文,不同的表去不同的全局ID上下文取。
另外一个,无论是中间件也好,应用也好,取全局ID时不要每次只取一个,那样性能太低了,更好的方式是每次取一段ID,比如应用1取到了1-50这段ID,那么它就可以在这50个ID用完之前,不再需要去取ID;应用2也去取ID,那么它会取到51-100这段ID,这个思想有点像储存食物过冬一样。
目前我这已知的方法:
1.修改原有的自增列,变为不自增主键。自己维护主键
2.水平拆分为拆分已有数据,也就是说拆分出去的表的数据不会再做变化。新增的数据依然自增。(注意不能设置自增填充空白id)
3.做个统一算法。自增id需要计算后写入,而不是自动维护
我这边之前也有这样的需求。
我是这么处理的:把主键列去掉自增长,通过redis的incr产生自增序列值,插入的时候指定id的值
1.把自增ID这个功能,用一张表与一个存储过程做成一个小模块。
2.被拆分的表,当有数据INSERT时,就调用这个存储过程来申请一个新ID。
分表后主键要自己生成最好,很多开源的主键生成策略算法,比如说twitter的snowflake等
如果不想改动程序的话,设置每个集群中自增 ID 起始点(auto_increment_offset)以及 ID 自增步长(auto_increment_increment),让目前每个集群的起始点错开,达到将 ID 相对分段的效果来满足全局唯一的效果。优点是实现简单,对应用透明,缺点就是,以后如果根据id做路由的话不好扩展