当前的消息推送系统设计中,每一个入库的消息必须要有一个全局严格递增ID。
一开始想到的自然是Long
9223372036854775807的最大值,够用到天荒地老,海枯石烂。
然后开始思考落地细节。
并发获取倒是没什么问题,LongAdder天助我也。
问题来了。
这样的ID为了严格递增,down机或重启后。
要保证能够产生比之前所有值都大的值继续生成。
1.这不久持久化吗,上一个最大ID不就在系统里?
不这么简单,后期的架构中,系统会针对推送主体产生茫茫多的推送队列。
每个队列在关系型数据库里就是一张表,在nosql数据库里就是一个对象。
每次重启,在这几十上百万甚至上千万张表或者对象中搜索一个最大数值。
不科学。
2.用时间,timestamp不是正好是Long?
重启后获得新的时间一定更大。
不太好,这样就限制了每秒最多1000个ID产生,并发瓶颈太低。
timestamp左移,剩下位用来递增?
嗯....左移后,大小可就不确定了。
况且有个万分之一的情况,服务器被时间回退。
3.傻乎乎地试了试Long后补数用decimal存,结果做索引效率和Long比起来,那是天差地别。
1000W条数据,分页查递增的1000条,一个0.037秒,一个23秒。
4.那就单独在配置表上留一个字段记录吧。
那么这个字段的更新频率也成为了性能瓶颈,一秒钟10W次写mysql,哪怕一个字段,也会蹦。
5.那就定时写?
每隔10秒,写入一次当前值,然后继续递增。
貌似也不妥,写完后递增一段时间后,突然挂了可咋整,这期间的递增数不久丢了?
一筹莫展之际。
等等,谁说定时写要写当前值!!!!!
比如当前值是0,提前预估个100W的提升,直接把100W写进库里,一定时间或者到达100W后再次写库,这样下次拿到的虽然不是连续递增,但是永远严格单调!
挂一次最多可能浪费100W?对Long来说简直毛毛毛毛毛毛毛毛毛雨。
解决!
网友评论