文章首发于:clawhub.club
最近有个需求,涉及到生成特定流水号:编码+14位时间YYYYMMDDHH24MMSS+6位流水号(定长),序号从000001开始,增量步长为1。
因为系统为集群部署,所以需要中间件来做后6位的增量计数。
redis的INCR命令正好合适:INCR 命令将 key 中储存的数字值增一,如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 INCR 操作。
因为系统使用的是jedis 2.9.0 所以封装了两个简单的方法:
接口:
1 2 3 4 5 6 7 8 9 10 11
|
long getAndIncrement(String key, int cacheSeconds);
|
单机版:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| @Override public long getAndIncrement(String key, int cacheSeconds) { long result = 0; Jedis jedis = null; try { jedis = pool.getResource(); result = jedis.incr(key); if (cacheSeconds != 0) { jedis.expire(key, cacheSeconds); } } catch (Exception e) { LOGGER.error("set " + key + " = " + result); } finally { IOUtils.close(jedis); } return result; }
|
集群版:
1 2 3 4 5 6 7 8 9 10 11 12 13
| @Override public long getAndIncrement(String key, int cacheSeconds) { long result = 0; try { result = jedisCluster.incr(key); if (cacheSeconds != 0) { jedisCluster.expire(key, cacheSeconds); } } catch (Exception e) { LOGGER.error("set " + key + " = " + result); } return result; }
|
代码中涉及到原子性问题,但是因为正好符合我的需求,所以就不成问题。
最终流水号生成方案:
1 2 3 4 5 6 7 8 9 10 11 12
|
private String getTransactionID() { String time = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")); String key = "xxx:xxxx:" + time; return REQUEST + time + String.format("%06d", getAndIncrement(key, 2) + 1); }
|