redis做分布式id

速度很快,一万个才半秒
最安全,比随机数安全多了
长度合适,不想随机数很长
16位id,比如2019073000000041,前八位日期,后八位redis计数器,格式化成八位长数字字符串

策略:
每个表作为hash的key,日期作为hashKey,计数器作为hash值
每天日期变更,使用新的hashKey,
之所以不覆盖旧的日期key,为了容错。假设集群下不同机器的时间有误差,可能这个机器是今天,另外机器是昨天。

定时任务删除前天的key,昨天的保留,适当冗余。

@Component
public class RedisId {
    private String DISTRIBUTE_ID = "DISTRIBUTE_ID:";
    private String date = LocalDate.now().toString().replace("-", "");

    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @Autowired
    private RedisLockRegistry redisLockRegistry;

    @Scheduled(cron = "0 0 0 0/1 * *")
    public void init() {
        deleteOldDays();

    }

    public void deleteOldDays() {
        //置换当前日期
        date = LocalDate.now().toString().replace("-", "");

        //删除前天的id
        Lock lock = redisLockRegistry.obtain("DELETE_OLD_DAYS");
        try {
            boolean b = lock.tryLock(1, TimeUnit.MINUTES);
            if (!b) {
                return;
            }
            Set<String> keys = redisTemplate.keys(DISTRIBUTE_ID + "*");
            if (keys == null || keys.size() == 0) {
                return;
            }

            String yesterday = LocalDate.now().minusDays(1).toString().replace("-", "");
            keys.forEach(key -> {
                Set<Object> daySet = redisTemplate.opsForHash().keys(key);
                if (daySet != null && daySet.size() > 0) {
                    daySet.forEach(day -> {
                        if (day.toString().compareTo(yesterday) < 0) {
                            redisTemplate.opsForHash().delete(key, day);
                        }
                    });
                }
            });
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public String getId() {
        return doGetId("COMMON");
    }

    public String getMachineId() {
        return doGetId("MACHINE");
    }

    private String doGetId(String key) {
        Long increment = redisTemplate.opsForHash().increment(DISTRIBUTE_ID + key, date, 1);
        return date + String.format("%08d", increment);
    }

}

每个表使用一个方法,提高并发性

使用举例


@RestController
@RequestMapping("/redisId")
public class RedisIdController {

    @Autowired
    private RedisId redisId;

    @RequestMapping("/commonId")
    public String commonId(){
        return redisId.getId();
    }

    @RequestMapping("/machineId")
    public String machineId(){
        return redisId.getMachineId();
    }

    @RequestMapping("/deleteOldDays")
    public String deleteOldDays(){
        redisId.deleteOldDays();
        return "deleteOldDays ok";
    }

    //一万个id才半秒,速度很快
    @RequestMapping("/manyId")
    public String manyId(){
        LocalDateTime now = LocalDateTime.now();
        for (int i = 0; i < 10000; i++) {
            redisId.getId();
        }
        System.out.println(Duration.between(now, LocalDateTime.now()));//PT0.511S
        return "manyId ok";
    }

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值