Redis Sentinel模式集成到Spring

Redis Sentinel模式集成到Spring

Author QiuRiMangCao 秋日芒草

引入jedis依赖jar

jedis-2.9.0.jar

bean 定义,spring为将这个bean包装成一个bean definition, destroy-method=”destroy” 就是对应redis.clients.jedis.JedisSentinelPool中的销毁方法

<bean id="jedisSentinelPool" class="redis.clients.jedis.JedisSentinelPool" destroy-method="destroy">
    // 对应redis.clients.jedis.JedisSentinelPool这个类中的构造器参数masterName的设置
    <constructor-arg name="masterName">
        // 读取资源文件的配置key=redis.sentinel.master.name
        <value>${redis.sentinel.master.name}</value>
    </constructor-arg>
    <constructor-arg name="sentinels">
        <set value-type="java.lang.String">
            <value>${redis.cluster.host1}</value>
            <value>${redis.cluster.host2}</value>
        </set>
    </constructor-arg>
    <constructor-arg name="password">
        <value>${redis.auth.password}</value>
    </constructor-arg>
    // ref="jedisPoolConfig" 引用另一个bean definition,这也是spring自动完成依赖注入的
    <constructor-arg name="poolConfig" ref="jedisPoolConfig" />
</bean>

对应properties 文件的配置信息如下

## Redis Cluster
redis.cluster.host1=127.0.0.1:26379
redis.cluster.host2=127.0.0.1:26379
redis.auth.password=
redis.sentinel.master.name=my_master

JedisSentinelPool 中存在JedisSentinelPool 多个构造器方法如下,可以选择不同的构造器进行初始化

public JedisSentinelPool(String masterName, Set<String> sentinels, String password) {
    this(masterName, sentinels, new GenericObjectPoolConfig(), Protocol.DEFAULT_TIMEOUT, password);
}

JedisPoolConfig extends GenericObjectPoolConfig,GenericObjectPoolConfig 类中有相关maxTotal的属性定义private int maxTotal = DEFAULT_MAX_TOTAL; 不设置会自动设置一个默认的值

<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
    <property name="minEvictableIdleTimeMillis" value="60000" />
    <property name="timeBetweenEvictionRunsMillis" value="30000" />
    <property name="numTestsPerEvictionRun" value="-1" />
    <property name="maxTotal" value="100" />
    <property name="maxIdle" value="50" />
    <property name="minIdle" value="10" />
    <property name="maxWaitMillis" value="1500"/>
</bean>

redis 工具类的,注入jedisSentinelPool,这样在容器启动后可以直接使用这个工具类来操作相关redis

<bean id="redisUtils" class="com.cn.redis.RedisUtils">
    <property name="jedisSentinelPool" ref="jedisSentinelPool" />
</bean>

redisUtils工具类代码

/**
 * @描述: Redis缓存工具类.
 */
public class RedisUtils {

    private static Logger logger = Logger.getLogger(RedisUtils.class);

    /** 默认缓存时间 */
    private static final int DEFAULT_CACHE_SECONDS = 60 * 60 * 1;// 单位秒 设置成一个钟

    /** 连接池 **/
    private static JedisSentinelPool jedisSentinelPool;

    /**
     * 释放redis资源
     * 
     * @param jedis
     */
    private static void releaseResource(Jedis jedis) {
        if (jedis != null) {
            jedis.close();
//          jedisSentinelPool.destroy(); 
//          jedisSentinelPool.returnResource(jedis);
        }
    }

    /**
     * 删除Redis中的所有key
     * 
     * @param jedis
     * @throws Exception
     */
    public static void flushAll() {
        Jedis jedis = null;
        try {
            jedis = jedisSentinelPool.getResource();

            String value = jedis.getSet("agui", "agui") ;

            jedis.flushAll();
        } catch (Exception e) {
            logger.error("Cache清空失败:" , e);
        } finally {
            releaseResource(jedis);
        }
    }

    /**
     * 保存一个对象到Redis中(缓存过期时间:使用此工具类中的默认时间) . <br/>
     * 
     * @param key
     *            键 . <br/>
     * @param object
     *            缓存对象 . <br/>
     * @return true or false . <br/>
     * @throws Exception
     */
    public static Boolean save(Object key, Object object) {
        return save(key, object, DEFAULT_CACHE_SECONDS);
    }

    /**
     * 保存一个对象到redis中并指定过期时间
     * 
     * @param key
     *            键 . <br/>
     * @param object
     *            缓存对象 . <br/>
     * @param seconds
     *            过期时间(单位为秒).<br/>
     * @return true or false .
     */
    public static Boolean save(Object key, Object object, int seconds) {
        Jedis jedis = null;
        try {
            jedis = jedisSentinelPool.getResource();
            jedis.set(SerializeUtils.serialize(key), SerializeUtils.serialize(object));
            jedis.expire(SerializeUtils.serialize(key), seconds);
            return true;
        } catch (Exception e) {
            logger.error("Cache保存失败:", e);
            return false;
        } finally {
            releaseResource(jedis);
        }
    }

    /**
     * 根据缓存键获取Redis缓存中的值.<br/>
     * 
     * @param key
     *            键.<br/>
     * @return Object .<br/>
     * @throws Exception
     */
    public static Object get(Object key) {
        Jedis jedis = null;
        try {
            jedis = jedisSentinelPool.getResource();
            byte[] obj = jedis.get(SerializeUtils.serialize(key));
            return obj == null ? null : SerializeUtils.unSerialize(obj);
        } catch (Exception e) {
            logger.error("Cache获取失败:" , e);
            return null;
        } finally {
            releaseResource(jedis);
        }
    }

    /**
     * 根据缓存键清除Redis缓存中的值.<br/>
     * 
     * @param key
     * @return
     * @throws Exception
     */
    public static Boolean del(Object key) {
        Jedis jedis = null;
        try {
            // System.out.println(key);
            jedis = jedisSentinelPool.getResource();
            jedis.del(SerializeUtils.serialize(key));
            return true;
        } catch (Exception e) {
            logger.error("Cache删除失败:" , e);
            return false;
        } finally {
            releaseResource(jedis);
        }
    }

    /**
     * 根据缓存键清除Redis缓存中的值.<br/>
     * 
     * @param keys
     * @return
     * @throws Exception
     */
    public static Boolean del(Object... keys) {
        Jedis jedis = null;
        try {
            jedis = jedisSentinelPool.getResource();
            jedis.del(SerializeUtils.serialize(keys));
            return true;
        } catch (Exception e) {
            logger.error("Cache删除失败:" , e);
            return false;
        } finally {
            releaseResource(jedis);
        }
    }

    /**
     * 
     * @param key
     * @param seconds
     *            超时时间(单位为秒)
     * @return
     */
    public static Boolean expire(Object key, int seconds) {

        Jedis jedis = null;
        try {
            jedis = jedisSentinelPool.getResource();
            jedis.expire(SerializeUtils.serialize(key), seconds);
            return true;
        } catch (Exception e) {
            logger.error("Cache设置超时时间失败:" , e);
            return false;
        } finally {
            releaseResource(jedis);
        }
    }

    /**
     * 添加一个内容到指定key的hash中
     * 
     * @param key
     * @param field
     * @param value
     * @return
     */
    public static Boolean addHash(String key, Object field, Object value) {
        Jedis jedis = null;
        try {
            jedis = jedisSentinelPool.getResource();
            jedis.hset(SerializeUtils.serialize(key), SerializeUtils.serialize(field), SerializeUtils.serialize(value));
            return true;
        } catch (Exception e) {
            logger.error("Cache保存失败:" , e);
            return false;
        } finally {
            releaseResource(jedis);
        }
    }

    /**
     * 从指定hash中拿一个对象
     * 
     * @param key
     * @param field
     * @return
     */
    public static Object getHash(Object key, Object field) {
        Jedis jedis = null;
        try {
            jedis = jedisSentinelPool.getResource();
            byte[] obj = jedis.hget(SerializeUtils.serialize(key), SerializeUtils.serialize(field));
            return SerializeUtils.unSerialize(obj);
        } catch (Exception e) {
            logger.error("Cache读取失败:" , e);
            return null;
        } finally {
            releaseResource(jedis);
        }
    }

    /**
     * 从hash中删除指定filed的值
     * 
     * @param key
     * @param field
     * @return
     */
    public static Boolean delHash(Object key, Object field) {
        Jedis jedis = null;
        try {
            jedis = jedisSentinelPool.getResource();
            long result = jedis.hdel(SerializeUtils.serialize(key), SerializeUtils.serialize(field));
            return result == 1 ? true : false;
        } catch (Exception e) {
            logger.error("Cache删除失败:" , e);
            return null;
        } finally {
            releaseResource(jedis);
        }
    }
    /**
     * 验证该值,在hash中是否存在。
     * 
     * @param key
     * @param field
     * @return
     */
    public static Boolean existsHash(Object key, Object field) {
        Jedis jedis = null;
        try {
            jedis = jedisSentinelPool.getResource();
            Boolean result = jedis.hexists(SerializeUtils.serialize(key), SerializeUtils.serialize(field));
            return result  ;
        } catch (Exception e) {
            logger.error("Cache验证hash 是否存在该值失败:" , e);
            return null;
        } finally {
            releaseResource(jedis);
        }
    }


    /**
     * 拿到缓存中所有符合pattern的key
     * 
     * @param pattern
     * @return
     */
    public static Set<byte[]> keys(String pattern) {
        Jedis jedis = null;
        try {
            jedis = jedisSentinelPool.getResource();
            Set<byte[]> allKey = jedis.keys(("*" + pattern + "*").getBytes());
            return allKey;
        } catch (Exception e) {
            logger.error("Cache获取失败:" , e);
            return new HashSet<byte[]>();
        } finally {
            releaseResource(jedis);
        }
    }

    /**
     * 获得hash中的所有key value
     * 
     * @param key
     * @return
     */
    public static Map<byte[], byte[]> getAllHash(Object key) {
        Jedis jedis = null;
        try {
            jedis = jedisSentinelPool.getResource();
            Map<byte[], byte[]> map = jedis.hgetAll(SerializeUtils.serialize(key));
            return map;
        } catch (Exception e) {
            logger.error("Cache获取失败:" , e);
            return null;
        } finally {
            releaseResource(jedis);
        }
    }

    /**
     * 判断一个key是否存在
     * 
     * @param key
     * @return
     */
    public static Boolean exists(Object key) {
        Jedis jedis = null;
        Boolean result = false;
        try {
            jedis = jedisSentinelPool.getResource();
            result = jedis.exists(SerializeUtils.serialize(key));
            return result;
        } catch (Exception e) {
            logger.error("Cache获取失败:" , e);
            return false;
        } finally {
            releaseResource(jedis);
        }
    }

    /**
     * 获取Redis中的key 的 ttl
     * 
     * @param jedis
     * @throws Exception
     */
    public static long getTtl(String key ) {
        Jedis jedis = null;
        try {
            jedis = jedisSentinelPool.getResource();
            return jedis.ttl(key) ;
        } catch (Exception e) {
            logger.error("Cache获取ttl失败:" , e);
        } finally {
            releaseResource(jedis);
        }
        return  0 ;
    }




    private static final String LOCK_NODE ="LOCK";
    private static ThreadLocal<String> local = new ThreadLocal<>();

    /**
     * 获取分布式锁
     * 
     * 弊端:只能是redis 单节点好用  所以要保证 该节点不能挂掉
     * 
     * 
     * @return
     */
    public static boolean getLock() {

        Jedis jedis = null;
        try {
            jedis =  jedisSentinelPool.getResource();
            String value = UUID.randomUUID().toString();
            String ret = jedis.set(LOCK_NODE, value, "NX", "PX", 10000);
            if(!StringUtils.isEmpty(ret) && ret.equals("OK")){
                local.set(value);
                return true;
            }
        } catch (Exception e) {
            logger.error("Cache获取锁失败:" , e);
            return false;
        } finally {
            releaseResource(jedis);
        }
        return false;

    }

    /**
     * 
     * 
     * 释放锁
     * 
     */
    public static void releaseLock() {
        String script =null;
        Jedis jedis = null ;
        try {
            script = FileCopyUtils.copyToString(new FileReader(ResourceUtils.getFile("classpath:unlock.lua")));
            jedis =  jedisSentinelPool.getResource(); 
            List<String> keys = new ArrayList<String>();
            keys.add(LOCK_NODE);
            List<String> args = new ArrayList<String>();
            args.add(local.get());
            jedis.eval(script, keys, args);
        } catch (IOException e) {
            logger.error("读取lua 脚本失败 :" + e.getMessage());
        } catch (Exception e) {
            logger.error("Cache释放锁失败:" , e);

        } finally {
            releaseResource(jedis);
        }

        System.out.println(script);

    }


    public void setJedisSentinelPool(JedisSentinelPool jedisSentinelPool) {
        RedisUtils.jedisSentinelPool = jedisSentinelPool;
    }

    public static JedisSentinelPool getJedisSentinelPool() {
        return jedisSentinelPool;
    }

}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值