This article is about one of the schemes of generating distributed Id. Besides redis schemes, there are other schemes such as database, snowflake algorithm, mogodb(object_id is also database) and so on. For redis, we often use them and have a lot of contacts. So we mainly talk about how to combine redis to generate distributed ID schemes.
- Distributed Id Design Flow Chart
- hash automatic increment cumulative generation of ordered Id based on redis
- Periodically delete useless hash columns
Distributed Id design flow chart (a bit rough)
hash automatic increment cumulative generation of ordered Id based on redis
The redis scheme is used to generate ids, one of which is increment, whether string or hash. In order to manage our id generation key s more conveniently, we recommend using hash columns. The following are based on spring boot sharing.
Of course, the first step is to create a hash and hkey. As for whether to create this hash by first accessing the business or automatically create it by service, the HKEY here has certain rules (without limitations of course). Here I do the key according to the date format, and can have the following code:
1 /** 2 * Generate the initial Id for each day 3 * @param hashName 4 * @return 5 */ 6 public String initPrimaryId(String hashName) { 7 Assert.hasLength(hashName, "hashName Can not be empty"); 8 9 String hashCol = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd")); 10 //Custom Numbering Rules 11 String hashColVal = hashCol + "00001"; 12 redisTemplate.opsForHash().putIfAbsent(hashName, hashCol, hashColVal); 13 return hashCol; 14 }
It's easy to understand that the key in hash is composed of a daily date format, which means that a new date key needs to be generated every day. Put IfAbsent achieves the principle of non-repetitive addition. As for hval, a series of numeric characters can be generated according to the customized numbering rules. Only increment is needed to accumulate, redis will help us complete the operation of hval+1, of course, you can customize the accumulated number, as follows:
1 /** 2 * Getting Distributed Id 3 * 4 * @param hashName 5 * @return 6 */ 7 public long getPrimaryId(String hashName) { 8 try { 9 String hashCol = initPrimaryId(hashName); 10 return redisTemplate.opsForHash().increment(hashName, hashCol, 1); 11 } catch (Exception ex) { 12 ex.printStackTrace(); 13 } 14 return 0; 15 }
Periodically delete useless hash columns
Above all, we use hash to set the initial value of each day id, hash's HKEY layout uses automatic expiration function, so we need to maintain a set of clearing HKEY mechanism in the code. Since ID is generated according to the date, we can use the way of pushing forward n days to achieve the purpose of clearing the old hkey:
1 /** 2 * How many days ago to delete cols 3 * @param hashName 4 * @param lessDay 5 * @return 6 */ 7 public Long removePrimaryByLessDay(String hashName, int lessDay) { 8 try { 9 //current date 10 String hashCol = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd")); 11 long idl = Long.valueOf(hashCol) - lessDay; 12 13 String[] removeCols = redisTemplate.opsForHash().entries(hashName).keySet().stream(). 14 map(key -> key.toString()). 15 filter(key -> idl > Long.valueOf(key)). //from+1 Start by avoiding deleting data for the day 16 toArray(String[]::new); 17 18 if (ArrayUtils.isNotEmpty(removeCols)) { 19 return redisTemplate.opsForHash().delete(hashName, removeCols); 20 } 21 } catch (Exception ex) { 22 ex.printStackTrace(); 23 } 24 return 0L; 25 }
To generate distributed IDS according to the date to achieve the purpose of not repeating ids, which is also distributed IDS (not repeating). It seems simple, but in fact, if the impact of high traffic, there are many things to consider, such as: when to generate the initial Id, in the case of multiple servers to ensure that the server time is as same as possible, the reservation. How many dates hkey and so on?
The above code is not very good for the initial Id. When the business acquires the Id, it detects and creates the id, so it interacts with redis more than once. Usually the service can be used to generate the hkey with the current date pushed back n days at a time. This avoids putIfAbsent verification when the business acquires the id, which reduces the cost of putIfAbsent verification. Number of requests. It's really not possible to use lua scripts to put and increment a request at a time. You might use:
1 RedisScript script = new DefaultRedisScript(""); 2 redisTemplate.execute(script, Arrays.asList(""));