It mainly uses the hashTags feature of Redis Cluster. Details can be found in the Keys hash tags chapter of https://redis.io/topics/cluster-spec .
My personal suggestion is to read the first half of this specification to understand why hash tags appear.
package com.xxxx.cms.common.support; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeSet; import org.apache.commons.collections4.CollectionUtils; import com.google.common.collect.Lists; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisCluster; import redis.clients.jedis.JedisPool; import redis.clients.util.JedisClusterCRC16; public interface RedisCacheSupporter { String SEPARATOR = RedisCacheBase.staticSeparator(); String CONJUNCTION = RedisCacheBase.staticConjunction(); String PLACEHOLDER = RedisCacheBase.staticPlaceHolder(); String LEFT_TAG_STR = RedisCacheBase.staticLeftTagStr(); String RIGHT_TAG_STR = RedisCacheBase.staticRightTagStr(); static String hashTagsPrefix(String cacheKeyPrefix) { return LEFT_TAG_STR + cacheKeyPrefix + RIGHT_TAG_STR; } static TreeSet<String> keys(JedisCluster jedisClusterClient, String cachePrefix) { Map<String, JedisPool> clusterNodes = jedisClusterClient.getClusterNodes(); TreeSet<String> keys = new TreeSet<>(); String strPattern = cachePrefix + "*"; for (String k : clusterNodes.keySet()) { JedisPool jp = clusterNodes.get(k); try (Jedis jedis = jp.getResource();) { if (jedis.info("replication").contains("role:slave")) continue; Set<String> keysInNode = jedis.keys(strPattern); keys.addAll(keysInNode); } } return keys; } static boolean delByKey(JedisCluster jedisClusterClient, String cacheKey) { return jedisClusterClient.del(cacheKey) > 0; } /** * This method is preferred for keys whose cache prefix is processed by hash tags {@link #hashTagsPrefix(String)} * <br/> * <br/> * Hash tags cannot be guaranteed to be in the same slot when reSharding in a redis cluster, so for the sake of code robustness, this method can be called first, and then the {@link #delLoopNodesByPrefix(JedisCluster, String)} method can be called to handle exceptions. * @param jedisClusterClient * @param cachePrefix */ static void delAllByPrefix(JedisCluster jedisClusterClient, String cachePrefix) { Set<String> keys = keys(jedisClusterClient, cachePrefix); if (CollectionUtils.isEmpty(keys)) { return; } jedisClusterClient.del(keys.toArray(new String[keys.size()])); } static void delLoopNodesByPrefix(JedisCluster jedisClusterClient, String cachePrefix) { String keysPattern = cachePrefix + "*"; Map<String, JedisPool> clusterNodes = jedisClusterClient.getClusterNodes(); for (String k : clusterNodes.keySet()) { JedisPool jedisPool = clusterNodes.get(k); try (Jedis jedis = jedisPool.getResource()) { if (jedis.info("replication").contains("role:slave")) continue;// The slave node does not process Set<String> keys = jedis.keys(keysPattern); if (keys.size() <= 0) continue; Map<Integer, List<String>> map = new HashMap<>(); for (String key : keys) { // When performing multiple key operations in cluster mode, these keys must be in the same slot // Otherwise, it will report: redis.clients.jedis.exceptions.JedisClusterException: // No way to dispatch this command to Redis Cluster because keys have different slots. int slot = JedisClusterCRC16.getSlot(key); // Group keys by slot, and submit keys of the same slot together if (map.containsKey(slot)) { map.get(slot).add(key); } else { map.put(slot, Lists.newArrayList(key)); } } for (Integer slotKey : map.keySet()) { jedis.del(map.get(slotKey).toArray(new String[map.get(slotKey).size()])); } } } } }
Then there is the key setting of the cached data for different pages of the same interface, in conjunction with the operation of hash tags.
package com.xxxxx.cms.stock.common.support; import com.xxxxx.cms.common.support.RedisCacheSupporter; import redis.clients.jedis.JedisCluster; public interface CachePrefix { String BASE_PREFIX = "cms:stock:plate:"; interface interfaceSpc { String PREFIX = BASE_PREFIX + "interface" + RedisCacheSupporter.SEPARATOR; static String contents(String plateCode) { return RedisCacheSupporter.hashTagsPrefix(PREFIX + "contents" + RedisCacheSupporter.SEPARATOR + plateCode + RedisCacheSupporter.SEPARATOR); } static void delCotentsAllCache(JedisCluster jedisClusterClient, String plateCode) { try { RedisCacheSupporter.delAllByPrefix(jedisClusterClient, contents(plateCode)); } catch (Exception e) { e.printStackTrace (); RedisCacheSupporter.delLoopNodesByPrefix(jedisClusterClient, contents(plateCode)); } } } }