雪花算法增强策略-扩充位数

背景

目前平台采用雪花算法作为主键生成策略。雪花算法有以下优点:

  1. 毫秒数在高位,自增序列在低位,整个ID都是趋势递增的。
  2. 不依赖数据库等第三方系统,以服务的方式部署,稳定性更高,生成ID的性能也是非常高的。
  3. 可以根据自身业务特性分配bit位,非常灵活

需求及目标

  • 原有的截取IP方式,很大可能性出现重复;
  • 需要将项目代码(AA~99)加入主键生成策略,而项目编码可能组合为1296个,需要占用至少11位的长度方能满足需求;
  • 基于以上需求,共计需要1(首位) + 41(时间戳差值) + 11(项目编码) + 5(机器Id) + 12(序列) = 70位;已经超出long类型的范围。

项目编码问题实现思路

项目编码目前为AA-99两个字符组合。如需加入主键生成运算,需要将AA-99转换成数字,本方案采用Ascall码的方式,分字符标识,列出所有可能,并返回一个数字,来将字符串转换成编码。

示例代码如下:

private static int getProjectId() {
    //项目编码
    String originalProjectId =  BeanUtils.getBean(Environment.class).getProperty(
    "liems.projectId", "AA");
    char[] projectCode = originalProjectId.toCharArray();
    //将项目编码的英文字母,转换为ascll码
    StringBuilder code = new StringBuilder();
    for (char c : projectCode) {
       code.append((int)c);
    }
    List<String> list = new ArrayList<>();
    for (int i = '0'; i <= 'Z'; i++) {
        for (int j = '0'; j <= 'Z'; j++) {
            list.add(i + "" + j);
        }
    }
    return list.indexOf(code.toString());
}

长度不够解决思路

在Java中,BigDecimal可以标识最大128位的数字。
BigDecimal使用示例

//起始时间
long START_STMP = 1288834974657L;
//以当前时间为例,计算时间戳差值
long time = System.currentTimeMillis() - START_STMP;
decimal = new BigDecimal(time);
//时间戳直接左移28位会导致直接溢出,所以此处采用乘法的方式
decimal = decimal.multiply(new BigDecimal(Math.pow(2, 28)));
//加入项目编码“AA”,左移17位(5位机器码 + 12位序列)
decimal = decimal.add(new BigDecimal(748 << 17));
//机器码左移12位
decimal = decimal.add(new BigDecimal(9 << 12));
decimal = decimal.add(new BigDecimal(0));

当前时间戳输出结果:87281447913632862208,转换成字符串后占用长度20
50年后的时间戳输出:856797335480725704704,转换成字符串后占用长度21,满足需求。

机器ID可能重复解决思路

在集群情况下,动态生成当前节点的编码。服务启动的时候,往Redis中放入IP+Port为Key的数据,以此来标记不同节点的机器编码,最大支持32个节点。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值