java jediscluster_方便jediscluster操作的工具类
由于redis的集群 redis cluster不支持keys這樣的多key操作(具體原因由于sharding 后,不同的key屬于不同的slot,難以支持原子操作)。所以如果一個對外需要對緩存做失效處理時比較棘手。所以本類提供工具方法再redis cluster查找按照hashTags處理的keys和一般的keys。基于jedis cluster實現。
有優化空間,現在懶得改了
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 keys(JedisCluster jedisClusterClient, String cachePrefix) {
Map clusterNodes = jedisClusterClient.getClusterNodes();
TreeSet 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 keysInNode = jedis.keys(strPattern);
keys.addAll(keysInNode);
}
}
return keys;
}
static boolean delByKey(JedisCluster jedisClusterClient, String cacheKey) {
return jedisClusterClient.del(cacheKey) > 0;
}
/**
* 緩存前綴通過hash tags {@link #hashTagsPrefix(String)}處理過的key首選使用本方法
*
*
* hash tags在redis集群reSharding時,不能保證都在同一slot下,所以為代碼健壯性考慮可首先調用本方法再捕獲異常中調用{@link #delLoopNodesByPrefix(JedisCluster, String)}方法處理
* @param jedisClusterClient
* @param cachePrefix
*/
static void delAllByPrefix(JedisCluster jedisClusterClient, String cachePrefix) {
Set 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 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;// 從節點不處理
Set keys = jedis.keys(keysPattern);
if (keys.size() <= 0)
continue;
Map> map = new HashMap<>();
for (String key : keys) {
// cluster模式執行多key操作的時候,這些key必須在同一個slot上
// 不然會報:redis.clients.jedis.exceptions.JedisClusterException:
// No way to dispatch this command to Redis Cluster because keys have different slots.
int slot = JedisClusterCRC16.getSlot(key);
// 按slot將key分組,相同slot的key一起提交
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()]));
}
}
}
}
}
總結
以上是生活随笔為你收集整理的java jediscluster_方便jediscluster操作的工具类的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 找不到java.vbs_无法找到脚本*.
- 下一篇: java客户端传递参数_java –