自主实现sequence

这篇文章,主要以思路为主吧,这样比较好做一点

      我们在开发mysql数据库为基础的程序时,比如用户数据,帖子等等乱七八糟的业务数据都可能需要生成一个唯一id,那这太简单了,我直接uuid生成唯一的id就行了,哦,如果你这样做,那这篇文章没必要写了,其实我挺不喜欢用

uuid做唯一id,因为这玩意是个很长的字符串,你看不出含义,我还是热衷于用数字来做唯一id

那有人又问了,mysql的主键id自增就行了,干嘛要sequence,我想原因应该是,数据库的自增id不适用于分布式存储,你懂得, 一旦单表做垂直拆分或者分库分表那自增id肯定会重复,这非常不靠谱,所以自增id仅仅用于数据库本身的管理,不应该当成业务唯一id来使用

但有个例外就是如果你的表非常小,充其量也就几百万数据量,那你拿主键id做唯一id查询,完全可以,一旦数据量大了,建议还是单独生成id好一些,这就是我们推崇的外键关联,而不是主键关联

在这里我多说一句,我不喜欢在数据库里做各种外键关联,虽然那样做使一些业务逻辑更严谨,但是坏处就是表之前的耦合太重,我们都是做互联网业务的,互联网业务变化非常频繁,我喜欢将这些关系拿到application层去做,数据库不设置任何强关联,这样有任何变更,我做表迁移和变更也没什么影响

所有的影响由代码级做控制。


好了,言归正传,我们要做一个sequence生成各个表的唯一id,那必然的,我们要建一个表叫sequence

例如:sequence{

id:bigint

name:varchar

value:bigint

info:varchar

}

      我用伪代码表示这个sequence表哈,为了写快一点,ok,想一下应用只有一台的情况下那就很好办了,由于应用访问dao都是多线程的,那读操作必然会出现幻读,所以我们要在application的dao层获取sequence时加锁,防止幻读生成重复的id出来;

流程就是:insert前,访问sequence中的某一行,将value +1,然后返回当前的value值,作为id insert到业务表中去

      上边的方法在单机情况下问题不大,但是会有性能问题,由于都是每次insert才去update sequence表获取下个id,还加了锁,多个表之间的insert相当于串行,效率很低;其实有个办法可以提高这个效率,就是我们建个本地缓存,在系统启动的时候,从sequence表里拉1000个增量出来,按表存到本机内存里,insert时只需要本机缓存里-1就行了,当1000个余额用完时,再去数据库批量拉去下一波,这样做会大大提高效率,降低频繁访问数据库的压力

      ok,如果是多个应用的情况呢,上边的办法显然不合适,那如何解决呢,我采用的是多机区间隔离的办法,比如说你有10台机器,那么你在系统初始化时,对这10台机器做个约定,按名字排序来,先拉10000个条sequence余额,a机器1--1000,b机器1001--2000,类似的道理你懂得,a机器用完了余额自动从10001--11000开始取值,想必大家已经明白我的意思了,呵呵,这的确是个好办法,采用这种约定后,应用之间互不冲突,效率还很高,至于实现还是很简单地,大家写写代码测试一下哈

      我本想写个sequence框架,简单点的,搜了一下github已经有好几个人都写了,大家不想自己搞去github上淘一下,这东西不是什么难事

转载于:https://my.oschina.net/glarystar/blog/471706

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值