开门见山地说,hilo高低位算法的用途,或者说目前为止我所见过的用途,就是——编号生成!
java
一般订单编号、产品编号、物流编号、工人编号、批次编号等等各类各样的编号,都是由数字构成,有得会加一些前缀后缀,例如淘宝订单号。这种编号比较符合咱们的理解和写记习惯。下面说一下几点不合理的编号设计。算法
使用数字型的自增加、序列。这用来表示惟一性没问题,可是当咱们遇到像订单编号这种,须要必定长度不太合适。数据库
编号须要必定长度,可能你会想到uuid。uuid生成的包含字符,无序、无心义并且也比较长,不符合咱们的写记习惯,因此uuid作编号也是不合理的。并发
使用时间戳来当编号,在并发的状况下精确到毫秒也有可能发生惟一性问题oracle
使用随机数加先后缀当编号,不少语言的随机数都是伪随机,例如用java每次都new Random(),并发的状况下有可能取出同样的数字,就算不并发,谁能保证不会随机到以前生成过的数字?dom
合理的作法是用表来管理数字主键,每次取出来拼接前缀或后缀来当编号,而后+1,就像oracle的序列同样,由于有些数据库没有序列,因此一般为了统一使用表来管理。性能
hilo高低位算法在这个时候登场了!优化
它解决了一个效率问题——每次取id号都要从数据库查一遍。ui
详细分析高低位算法:spa
/*首先有这几个静态变量和常量*/ long static final maxLo;//最大低位 long static hi=0;//高位初始化 long static lo=maxLo+1;//低位初始化,这样是为了从新初始化的时候进入下面的判断方法 /*每次生成都进行下面的判断*/ if(lo>maxLo){//当低位超过最大高位 long lastValue//表示hi位的进位次数,从数据库id管理表获取 lo=0;//低位归0 hi=lastValue*(maxLo+1);//高位进位 lastValue++//自增并更新到数据库中 } long id=ho+lo; lo++;//低位最后自增
若maxLo设置为99,按照hi的每次进位划分,产生的id形式是:
0~99,100~199,200~299,300~399……依此类推,每一个阶段99+1个
分析了hilo算法,它其实优化了相似oracle序列这种由数据库管理的id,每次插入都必须查询一遍数据库这种模式,用一个静态变量低位当成一个oracle序列,当它增加超过设置的最大低位时再查询数据库,减小查询数据库的次数maxLo倍!从而提高了项目的效率和性能。
Hibernate中的hilo主键生成策略的就是为了提升oracle使用序列当主键的效率问题。
若是你不在意这点效率问题,就不用hilo算法了,不过我最后说一下题外话,不管本身写代码生成编号使不使用hilo算法,都应该防止并发操做,例如使用java的synchronized。