package com.pingan.pss.sales.ucenter.common.util;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.stereotype.Service;
import redis.clients.jedis.*;
import redis.clients.jedis.exceptions.JedisNoReachableClusterNodeException;
import redis.clients.jedis.util.JedisClusterCRC16;
import java.util.*;
/**
-
@author yanzj
-
@version V-1.0
-
@date 2021/8/18 20:30
-
@description 根据key计算槽位,根据槽位获取实例连接池,以此来将数据分组,批量set,如果无法获取连接池,则槽位发生变化,刷新缓存
-
@Waring 只支持集群模式使用
*/
@Service
public class JedisClusterUtil implements InitializingBean {@Autowired
JedisConnectionFactory jedisConnectionFactory;private JedisClusterInfoCache jedisClusterInfoCache;
/String Key/
public void jedisPipeline(Map resMap, Long millisecondsExpire){
Map<JedisPool, Map> cacheMap = getNeedCacheInfoMap(resMap);
cacheMap.forEach((key,value) -> {
Jedis jedisResource = key.getResource();
Pipeline pipeline = jedisResource.pipelined();
Iterator<Map.Entry<String, Object>> iterator = value.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, Object> next = iterator.next();
pipeline.psetex(next.getKey(), millisecondsExpire, JSONObject.toJSONString(next.getValue(), SerializerFeature.WriteMapNullValue));
}
pipeline.sync();
jedisResource.close();
});
}/**Hash Key
- 注意 如果需要使用该方法,一定要用UcenterCacheCommonUtil.SerializerValue 来对 hash map的value进行序列化
- 详见例子 IsEmployeeeAgentBaseInfoHandlerImpl.parseBaseInfo
- 如果不按照上面的操作,在查询会反序列化异常
- 如果不是需要对集群批量操作
- 建议直接使用redisTemplate操作 **/
public void jedisPipelineHash(Map resMap, Long millisecondsExpire){
Map<JedisPool, Map> cacheMap = getNeedCacheInfoMap(resMap);
cacheMap.forEach((key,value) -> {
Jedis jedisResource = key.getResource();
Pipeline pipeline = jedisResource.pipelined();
Iterator<Map.Entry<String, Object>> iterator = value.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, Object> next = iterator.next();
pipeline.hmset(next.getKey().getBytes(), (Map<byte[], byte[]>) next.getValue());
pipeline.pexpire(next.getKey(),millisecondsExpire);
}
pipeline.sync();
jedisResource.close();
});
}
/List Key/
public void jedisPipelineList(Map<String, List> resMap, Long millisecondsExpire) {
Map<JedisPool, Map> cacheMap = getNeedCacheInfoMap(resMap);
cacheMap.forEach((key,value) -> {
Jedis jedisResource = key.getResource();
Pipeline pipeline = jedisResource.pipelined();
Iterator<Map.Entry<String, Object>> iterator = value.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, Object> next = iterator.next();
String redisKey = next.getKey();
LinkedList/common/
private Map getNeedCacheInfoMap(Map resMap){
Map<JedisPool, Map> cacheMap = new HashMap<>();
// 计算hash slot,根据特定的slot可以获取到特定的Redis实例
resMap.forEach((key,value)->{
int slot = JedisClusterCRC16.getSlot((String) key);
JedisPool jedisPoolFromSlot = jedisClusterInfoCache.getSlotPool(slot);
if (jedisPoolFromSlot == null) {
jedisClusterInfoCache.renewClusterSlots(null); //It’s abnormal situation for cluster mode, that we have just nothing for slot, try to rediscover state
jedisPoolFromSlot = jedisClusterInfoCache.getSlotPool(slot);
if (jedisPoolFromSlot == null) {
throw new JedisNoReachableClusterNodeException(“No reachable node in cluster”);
}
}
if (cacheMap.containsKey(jedisPoolFromSlot)){
Map map = cacheMap.get(jedisPoolFromSlot);
map.put(key,value);
}else {
Map subMap = new HashMap<>();
subMap.put(key,value);
cacheMap.put(jedisPoolFromSlot,subMap);
}
});
return cacheMap;
}@Override
public void afterPropertiesSet() throws Exception {
JedisCluster jedisCluster = (JedisCluster) SystemMetaObject.forObject(jedisConnectionFactory).getValue(“cluster”);
this.jedisClusterInfoCache = (JedisClusterInfoCache) SystemMetaObject.forObject(jedisCluster).getValue(“connectionHandler.cache”);
}
}