Redis集群批量set Key工具类

该代码段展示了如何在Java中利用JedisCluster工具类进行Redis集群的键槽位计算、批量设置键值对、哈希及列表操作,并在无法获取连接池时进行异常处理和缓存刷新。主要涉及Redis的Pipeline和JedisClusterInfoCache功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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 nextValue = (LinkedList) next.getValue();
    //先删除key
    pipeline.del(redisKey);
    for (Map ve : nextValue) {
    pipeline.rpush(redisKey,JSONObject.toJSONString(ve));
    }
    pipeline.pexpire(next.getKey(),millisecondsExpire);
    }
    pipeline.sync();
    jedisResource.close();
    });
    }

    /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”);
    }
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值