一个美女辩题进我的旁,荧光logo的MacBook,也挡不住她那圆润乖巧的面孔。
业务流程媛本就稀有,美女辩题着实难寻。具体内容长什么样呢?就像下面此种:
所以温柔乖巧的辩题,假如不能怨恨我吧。嗯,假如是的,即使我所以帅气,面试可能就是走个口白。美女辩题呢已婚?即使开发者都不善沟通,因为我也是已婚,更何况我的姻缘就在此也许。小孩的英文名我都想好了。一冰!好英文名。
辩题:小伙子,你面带微笑笑甚么呐。开始面试了,你知道供货ID是呢裂解的吗?
啥?供货ID呢裂解?美女呢不按拳术翻牌!HashMap与此同时与此同时实现基本概念,我已经LX1,你若非。瞎问什么供货ID。
我:还能咋裂解?用数据库操作符自增呗。
辩题:此种不行啊。数据库操作符顺序自增,每天晚上有啥供货量被竞争对手看得一清二楚,商业性机密都暴露了。 况且FPSMySQL根本无法全力支持几百量级的mammalian,他们控股公司每天晚上一千万供货量,hold狡蛛属啊。
我:嗯,那就用用数据库信息产业,自增ID科蚜狼按笔记本电脑序列号,自变量等同笔记本电脑数目。比如说有两台笔记本电脑,第一台笔记本电脑裂解的ID是1、3、5、7,第二台笔记本电脑裂解的ID是2、4、6、8。舒适性不行就加笔记本电脑,这mammalian量der呵呵就上去了。
辩题:小伙子,你想得倒是说实话的。你呢Dharmapuri与此同时与此同时实现一千万级的mammalian,仅约就需要2000台笔记本电脑,你这还只是借以裂解供货ID,控股公司再有钱有势也挡狡蛛属所以造。
我:何况MySQL的mammalian量不行,他们呢可以提早从MySQL以获取一大批自增ID,加载到邻近地区缓存中,然后从缓存中mammalian取,这mammalian舒适性何必会门滴。
辩题:你还挺上道,此种叫科季夫商业性模式。mammalian量是上去了,但是自增ID还是不能作为供货ID的。
我:用Java便携式UUID呢样?
importjava.util.UUID;/** *@authoryideng *@apiNoteUUID示例 */publicclassUUIDTest{publicstaticvoidmain(String[] args){ String orderId = UUID.randomUUID().toString().replace("-",""); System.out.println(orderId); } }输出结果:
58e93ecab9c64295b15f7f4661edcbc1辩题:也不行。32位字符串会占用更大的空间,无序的字符串作数据库操作符,每次插入数据库的时候,MySQL为了维护B+树结构,需要频繁调整节点顺序,影响舒适性。况且字符串太长,也没有任何业务含义,pass。
小伙子,你可能是没参与过电商系统,我先跟说呵呵裂解供货ID要满足哪些条件:
全局唯一:假如供货ID重复了,肯定要完蛋。高舒适性:要做到高mammalian、低延迟。裂解供货ID都成为瓶颈了,那还得了。高可用:至少要做到4个9,别动狡蛛属就宕机了。易用性:假如为了满足上述要求,搞了几百台服务器,复杂且难以维护,也不行。数值且有序递增:数值占用的空间更小,有序递增能保证插入MySQL的时候更高舒适性。嵌入业务含义:假如供货ID里面能嵌入业务含义,就能通过供货ID知道是哪个业务线裂解的,便于排查问题。
,裂解一个小小的供货ID,搞出所以多规则,还能玩下去吗?更何况今天的面试要跪,呢可能。一灯的文章我一直订阅,这个还能难得住我,陪美女开发者玩玩还当真了。
我:我听说圈内有一种流传已久的分布式、高舒适性、高可用的供货ID裂解算法—雪花算法,完全能满足你的上述要求。雪花算法裂解ID是Long类型,长度64位。
第 1 位: 符号位,暂时不用。第 2~42 位:共41位,时间戳,单位是毫秒,可以支撑大约69年第 43~52 位:共10位,笔记本电脑ID,最多可容纳1024台笔记本电脑第 53~64 位:共12位,序列号,是自增值,表示同一毫秒内产生的ID,单台笔记本电脑每毫秒最多可裂解4096个供货ID
代码与此同时与此同时实现:
/** * @author 一灯架构 * @apiNote 雪花算法 **/publicclassSnowFlake{/** * 起始时间戳,从2021-12-01开始裂解 */privatefinalstaticlongSTART_STAMP =1638288000000L;/** * 序列号占用的位数 12 */privatefinalstaticlongSEQUENCE_BIT =12;/** * 笔记本电脑标识占用的位数 */privatefinalstaticlongMACHINE_BIT =10;/** * 笔记本电脑数目最大值 */privatefinalstaticlongMAX_MACHINE_NUM = ~(-1L<< MACHINE_BIT);/** * 序列号最大值 */privatefinalstaticlongMAX_SEQUENCE = ~(-1L<< SEQUENCE_BIT);/** * 每一部分向左的位移 */privatefinalstaticlongMACHINE_LEFT = SEQUENCE_BIT;privatefinalstaticlongTIMESTAMP_LEFT = SEQUENCE_BIT + MACHINE_BIT;/** * 笔记本电脑标识 */privatelongmachineId;/** * 序列号 */privatelongsequence =0L;/** * 上一次时间戳 */privatelonglastStamp =-1L;/** * 构造方法 * @param machineId 笔记本电脑ID */publicSnowFlake(longmachineId){if(machineId > MAX_MACHINE_NUM || machineId <0) {thrownewRuntimeException("笔记本电脑超过最大数目"); }this.machineId = machineId; }/** * 产生下一个ID */publicsynchronizedlongnextId(){longcurrStamp = getNewStamp();if(currStamp < lastStamp) {thrownewRuntimeException("时钟后移,拒绝裂解ID!"); }if(currStamp == lastStamp) {// 相同毫秒内,序列号自增sequence = (sequence +1) & MAX_SEQUENCE;// 同一毫秒的序列数已经达到最大if(sequence ==0L) { currStamp = getNextMill(); } }else{// 不同毫秒内,序列号置为0sequence =0L; } lastStamp = currStamp;return(currStamp - START_STAMP) << TIMESTAMP_LEFT// 时间戳部分| machineId << MACHINE_LEFT// 笔记本电脑标识部分| sequence;// 序列号部分}privatelonggetNextMill(){longmill = getNewStamp();while(mill <= lastStamp) { mill = getNewStamp(); }returnmill; }privatelonggetNewStamp(){returnSystem.currentTimeMillis(); }publicstaticvoidmain(String[] args){// 供货ID裂解测试,笔记本电脑ID指定第0台SnowFlake snowFlake =newSnowFlake(0); System.out.println(snowFlake.nextId()); } }输出结果:
6836348333850624接入非常简单,不需要搭建服务信息产业,。代码逻辑非常简单,,同一毫秒内,供货ID的序列号自增。同步锁只作用于本机,笔记本电脑之间互不影响,每毫秒可以4一千万的供货ID,非常强悍。
裂解规则不是固定的,可以根据自身的业务需求调整。假如你不需要所以大的mammalian量,可以把笔记本电脑标识位拆出一部分,当作业务标识位,标识是哪个业务线裂解的供货ID。
辩题:小伙子,有点东西,深藏不漏啊。再问个更难的问题,你觉得雪花算法还有改进的空间吗?
你真是打破砂锅问到底,不把我问趴下不结束。幸亏来之前我瞥了一眼一灯的文章。
我:有的,雪花算法严重依赖系统时钟。假如时钟回拨,就会裂解重复ID。
辩题:有什么解决办法吗?
我:有问题就会有答案。比如说美团的Leaf(美团自研一种分布式ID裂解系统),为了解决时钟回拨,引入了zookeeper,基本概念也很简单,就是比较当前系统时间跟裂解节点的时间。
有的对mammalian要求更高的系统,比如说双十一秒杀,每毫秒4一千万mammalian还不能满足要求,就可以使用雪花算法和科季夫商业性模式相结合,比如说百度的UidGenerator、滴滴的TinyId。想想也是,科季夫商业性模式的预先裂解ID肯定是高舒适性分布式供货ID的最终解决方案。
辩题:小伙子,我看你简历上写着已经离职了。明天就来上班吧,薪资double,就此种了。