spring-data-redis与JedisPool的区别、使用ShardedJedisPool与spring集成的实现及一致性哈希分析

一、Redis与spring的整合一般分为spring-data-redis整合和JedisPool整合,先看看两者的区别

1)、引用的依赖不同:

spring-data-redis使用的依赖如下:

<span style="color:#000000"><code>    <span style="color:#006666"><<span style="color:#4f4f4f">dependency</span>></span>  
        <span style="color:#006666"><<span style="color:#4f4f4f">groupId</span>></span>org.springframework.data<span style="color:#006666"></<span style="color:#4f4f4f">groupId</span>></span>  
        <span style="color:#006666"><<span style="color:#4f4f4f">artifactId</span>></span>spring-data-redis<span style="color:#006666"></<span style="color:#4f4f4f">artifactId</span>></span>  
        <span style="color:#006666"><<span style="color:#4f4f4f">version</span>></span>1.0.2.RELEASE<span style="color:#006666"></<span style="color:#4f4f4f">version</span>></span>  
    <span style="color:#006666"></<span style="color:#4f4f4f">dependency</span>></span></code></span>

JedisPool使用的依赖如下:

<span style="color:#000000"><code>    <span style="color:#006666"><<span style="color:#4f4f4f">dependency</span>></span>
        <span style="color:#006666"><<span style="color:#4f4f4f">groupId</span>></span>redis.clients<span style="color:#006666"></<span style="color:#4f4f4f">groupId</span>></span>
        <span style="color:#006666"><<span style="color:#4f4f4f">artifactId</span>></span>jedis<span style="color:#006666"></<span style="color:#4f4f4f">artifactId</span>></span>
        <span style="color:#006666"><<span style="color:#4f4f4f">version</span>></span>2.7.2<span style="color:#006666"></<span style="color:#4f4f4f">version</span>></span>
        <span style="color:#006666"><<span style="color:#4f4f4f">type</span>></span>jar<span style="color:#006666"></<span style="color:#4f4f4f">type</span>></span>
        <span style="color:#006666"><<span style="color:#4f4f4f">scope</span>></span>compile<span style="color:#006666"></<span style="color:#4f4f4f">scope</span>></span>
    <span style="color:#006666"></<span style="color:#4f4f4f">dependency</span>></span></code></span>

2)、管理Jedis实例方式、操作redis服务的不同:

spring-data-redis:

通过org.springframework.data.redis.connection.jedis.JedisConnectionFactory来管理,即通过工厂类管理,然后通过配置的模版bean,操作redis服务,代码段中充斥大量与业务无关的模版片段代码,代码冗余,不易维护,比如像下面的代码:

<span style="color:#000000"><code>    <span style="color:#9b859d">@Autowired</span>
    <span style="color:#000088">protected</span> RedisTemplate<Serializable, Serializable> redisTemplate;

    <span style="color:#000088">public</span> <span style="color:#000088">void</span> <span style="color:#009900">saveUser</span>(<span style="color:#000088">final</span> User user) {
        redisTemplate.execute(<span style="color:#000088">new</span> RedisCallback<Object>() {

            <span style="color:#9b859d">@Override</span>
            <span style="color:#000088">public</span> Object <span style="color:#009900">doInRedis</span>(RedisConnection connection) <span style="color:#000088">throws</span> DataAccessException {
                connection.set(redisTemplate.getStringSerializer().serialize(<span style="color:#009900">"user.uid."</span> + user.getId()),
                               redisTemplate.getStringSerializer().serialize(user.getName()));
                <span style="color:#000088">return</span> <span style="color:#000088">null</span>;
            }
        });
    }</code></span>
<span style="color:#000000"><code><span style="color:#9b859d">@Override</span>
    <span style="color:#000088">public</span> User <span style="color:#009900">getUser</span>(<span style="color:#000088">final</span> <span style="color:#000088">long</span> id) {
        <span style="color:#000088">return</span> redisTemplate.execute(<span style="color:#000088">new</span> RedisCallback<User>() {
            <span style="color:#9b859d">@Override</span>
            <span style="color:#000088">public</span> User <span style="color:#009900">doInRedis</span>(RedisConnection connection) <span style="color:#000088">throws</span> DataAccessException {
                <span style="color:#000088">byte</span>[] key = redisTemplate.getStringSerializer().serialize(<span style="color:#009900">"user.uid."</span> + id);
                <span style="color:#000088">if</span> (connection.exists(key)) {
                    <span style="color:#000088">byte</span>[] value = connection.get(key);
                    String name = redisTemplate.getStringSerializer().deserialize(value);
                    User user = <span style="color:#000088">new</span> User();
                    user.setName(name);
                    user.setId(id);
                    <span style="color:#000088">return</span> user;
                }
                <span style="color:#000088">return</span> <span style="color:#000088">null</span>;
            }
        });
    }</code></span>

JedisPool方式:

通过redis.clients.jedis.JedisPool来管理,即通过池来管理,通过池对象获取jedis实例,然后通过jedis实例直接操作redis服务,剔除了与业务无关的冗余代码,如下面的代码片段:

<span style="color:#000000"><code>    <span style="color:#9b859d">@Autowired</span>
    <span style="color:#000088">private</span> JedisPool jedisPool;

    <span style="color:#9b859d">@Override</span>
    <span style="color:#000088">public</span> String <span style="color:#009900">save</span>(String key,String val) {
        Jedis jedis = jedisPool.getResource();
        <span style="color:#000088">return</span> jedis.set(key, val);

    }
</code></span>

从工厂类到池的方式变化,就相当于mybatis连接mysql方变化是一样的,代码变得更简洁,维护也更容易了。

spring-data-redis的集成方式可以查看 java之redis篇(spring-data-redis整合) 这边博文。

但是本文与spring集成并未直接采用JedisPool,而是采用了 ShardedJedisPool ,为什么呢?

因为ShardedJedisPool可以通过一致性哈希实现分布式存储

shared一致性哈希采用以下方案:

1、Redis服务器节点划分:将每台服务器节点采用hash算法划分为160个虚拟节点(可以配置划分权重)

2、将划分虚拟节点采用TreeMap存储

3、对每个Redis服务器的物理连接采用LinkedHashMap存储

4、对Key or KeyTag 采用同样的hash算法,然后从TreeMap获取大于等于键hash值得节点,取最邻近节点存储;当key的hash值大于虚拟节点hash值得最大值时,存入第一个虚拟节点sharded采用的hash算法:MD5 和 MurmurHash两种;默认采用64位的MurmurHash算法;

更为深入解释可以查看 Jedis分片连接池(分布式) 、 jedis源码中ShardedJedis实现sharding文章。

使用非分片的JedisPool和使用分片的ShardedJedisPool示例可以查看 Java内存数据库实践之深入浅出Redis - Jedis分布式(Sharding/Sharded) 这篇文章。

二、使用ShardedJedisPool与spring集成

集成参照:https://my.oschina.net/u/866380/blog/521658

相关依赖jar包

<span style="color:#000000"><code>    <span style="color:#006666"><<span style="color:#4f4f4f">properties</span>></span>
        <span style="color:#006666"><<span style="color:#4f4f4f">project.build.sourceEncoding</span>></span>UTF-8<span style="color:#006666"></<span style="color:#4f4f4f">project.build.sourceEncoding</span>></span>
        <span style="color:#006666"><<span style="color:#4f4f4f">spring.version</span>></span>4.2.6.RELEASE<span style="color:#006666"></<span style="color:#4f4f4f">spring.version</span>></span>
    <span style="color:#006666"></<span style="color:#4f4f4f">properties</span>></span>

    <span style="color:#006666"><<span style="color:#4f4f4f">dependencies</span>></span>

        <span style="color:#880000"><!-- spring begin --></span>
        <span style="color:#006666"><<span style="color:#4f4f4f">dependency</span>></span>
            <span style="color:#006666"><<span style="color:#4f4f4f">groupId</span>></span>org.springframework<span style="color:#006666"></<span style="color:#4f4f4f">groupId</span>></span>
            <span style="color:#006666"><<span style="color:#4f4f4f">artifactId</span>></span>spring-context<span style="color:#006666"></<span style="color:#4f4f4f">artifactId</span>></span>
            <span style="color:#006666"><<span style="color:#4f4f4f">version</span>></span>${spring.version}<span style="color:#006666"></<span style="color:#4f4f4f">version</span>></span>
        <span style="color:#006666"></<span style="color:#4f4f4f">dependency</span>></span>
        <span style="color:#006666"><<span style="color:#4f4f4f">dependency</span>></span>
            <span style="color:#006666"><<span style="color:#4f4f4f">groupId</span>></span>org.springframework<span style="color:#006666"></<span style="color:#4f4f4f">groupId</span>></span>
            <span style="color:#006666"><<span style="color:#4f4f4f">artifactId</span>></span>spring-context-support<span style="color:#006666"></<span style="color:#4f4f4f">artifactId</span>></span>
            <span style="color:#006666"><<span style="color:#4f4f4f">version</span>></span>${spring.version}<span style="color:#006666"></<span style="color:#4f4f4f">version</span>></span>
        <span style="color:#006666"></<span style="color:#4f4f4f">dependency</span>></span>
        <span style="color:#006666"><<span style="color:#4f4f4f">dependency</span>></span>
            <span style="color:#006666"><<span style="color:#4f4f4f">groupId</span>></span>org.springframework<span style="color:#006666"></<span style="color:#4f4f4f">groupId</span>></span>
            <span style="color:#006666"><<span style="color:#4f4f4f">artifactId</span>></span>spring-test<span style="color:#006666"></<span style="color:#4f4f4f">artifactId</span>></span>
            <span style="color:#006666"><<span style="color:#4f4f4f">version</span>></span>${spring.version}<span style="color:#006666"></<span style="color:#4f4f4f">version</span>></span>
        <span style="color:#006666"></<span style="color:#4f4f4f">dependency</span>></span>


        <span style="color:#006666"><<span style="color:#4f4f4f">dependency</span>></span>
            <span style="color:#006666"><<span style="color:#4f4f4f">groupId</span>></span>redis.clients<span style="color:#006666"></<span style="color:#4f4f4f">groupId</span>></span>
            <span style="color:#006666"><<span style="color:#4f4f4f">artifactId</span>></span>jedis<span style="color:#006666"></<span style="color:#4f4f4f">artifactId</span>></span>
            <span style="color:#006666"><<span style="color:#4f4f4f">version</span>></span>2.7.2<span style="color:#006666"></<span style="color:#4f4f4f">version</span>></span>
            <span style="color:#006666"><<span style="color:#4f4f4f">type</span>></span>jar<span style="color:#006666"></<span style="color:#4f4f4f">type</span>></span>
        <span style="color:#006666"></<span style="color:#4f4f4f">dependency</span>></span>

        <span style="color:#006666"><<span style="color:#4f4f4f">dependency</span>></span>
            <span style="color:#006666"><<span style="color:#4f4f4f">groupId</span>></span>junit<span style="color:#006666"></<span style="color:#4f4f4f">groupId</span>></span>
            <span style="color:#006666"><<span style="color:#4f4f4f">artifactId</span>></span>junit<span style="color:#006666"></<span style="color:#4f4f4f">artifactId</span>></span>
            <span style="color:#006666"><<span style="color:#4f4f4f">version</span>></span>4.11<span style="color:#006666"></<span style="color:#4f4f4f">version</span>></span>
            <span style="color:#006666"><<span style="color:#4f4f4f">scope</span>></span>test<span style="color:#006666"></<span style="color:#4f4f4f">scope</span>></span>
        <span style="color:#006666"></<span style="color:#4f4f4f">dependency</span>></span>
    <span style="color:#006666"></<span style="color:#4f4f4f">dependencies</span>></span></code></span>

Spring 配置文件spring-redis.xml

<span style="color:#000000"><code><span style="color:#006666"><?xml version="1.0" encoding="UTF-8"?></span>
<span style="color:#006666"><<span style="color:#4f4f4f">beans</span>  <span style="color:#4f4f4f">xmlns</span>=<span style="color:#009900">"http://www.springframework.org/schema/beans"</span> 
        <span style="color:#4f4f4f">xmlns:xsi</span>=<span style="color:#009900">"http://www.w3.org/2001/XMLSchema-instance"</span>       
        <span style="color:#4f4f4f">xmlns:context</span>=<span style="color:#009900">"http://www.springframework.org/schema/context"</span> 
        <span style="color:#4f4f4f">xsi:schemaLocation</span>=<span style="color:#009900">"
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"</span>></span>

    <span style="color:#880000"><!-- 开启注解驱动 --></span>
    <span style="color:#006666"><<span style="color:#4f4f4f">context:annotation-config</span>></span><span style="color:#006666"></<span style="color:#4f4f4f">context:annotation-config</span>></span>

    <span style="color:#880000"><!-- 引入属性文件 --></span>
    <span style="color:#006666"><<span style="color:#4f4f4f">context:property-placeholder</span> <span style="color:#4f4f4f">location</span>=<span style="color:#009900">"classpath:spring-redis.properties"</span> <span style="color:#4f4f4f">ignore-unresolvable</span>=<span style="color:#009900">"true"</span> /></span>

    <span style="color:#880000"><!-- 配置redis数据库连接池 --></span>
    <span style="color:#006666"><<span style="color:#4f4f4f">bean</span> <span style="color:#4f4f4f">id</span>=<span style="color:#009900">"jedisPoolConfig"</span> <span style="color:#4f4f4f">class</span>=<span style="color:#009900">"redis.clients.jedis.JedisPoolConfig"</span>></span>
        <span style="color:#006666"><<span style="color:#4f4f4f">property</span> <span style="color:#4f4f4f">name</span>=<span style="color:#009900">"maxTotal"</span> <span style="color:#4f4f4f">value</span>=<span style="color:#009900">"${redis.pool.maxActive}"</span> /></span>
        <span style="color:#006666"><<span style="color:#4f4f4f">property</span> <span style="color:#4f4f4f">name</span>=<span style="color:#009900">"maxIdle"</span> <span style="color:#4f4f4f">value</span>=<span style="color:#009900">"${redis.pool.maxIdle}"</span> /></span>
        <span style="color:#006666"><<span style="color:#4f4f4f">property</span> <span style="color:#4f4f4f">name</span>=<span style="color:#009900">"minIdle"</span> <span style="color:#4f4f4f">value</span>=<span style="color:#009900">"${redis.pool.minIdle}"</span> /></span>
        <span style="color:#006666"><<span style="color:#4f4f4f">property</span> <span style="color:#4f4f4f">name</span>=<span style="color:#009900">"maxWaitMillis"</span> <span style="color:#4f4f4f">value</span>=<span style="color:#009900">"${redis.pool.maxWait}"</span> /></span>
        <span style="color:#006666"><<span style="color:#4f4f4f">property</span> <span style="color:#4f4f4f">name</span>=<span style="color:#009900">"lifo"</span> <span style="color:#4f4f4f">value</span>=<span style="color:#009900">"${redis.pool.lifo}"</span> /></span>
        <span style="color:#006666"><<span style="color:#4f4f4f">property</span> <span style="color:#4f4f4f">name</span>=<span style="color:#009900">"testOnBorrow"</span> <span style="color:#4f4f4f">value</span>=<span style="color:#009900">"${redis.pool.testOnBorrow}"</span> /></span>
    <span style="color:#006666"></<span style="color:#4f4f4f">bean</span>></span>

    <span style="color:#880000"><!-- 配置redis共享连接池,业务层主要通过该bean访问redis服务器 --></span>
    <span style="color:#006666"><<span style="color:#4f4f4f">bean</span> <span style="color:#4f4f4f">id</span>=<span style="color:#009900">"shardedJedisPool"</span> <span style="color:#4f4f4f">class</span>=<span style="color:#009900">"redis.clients.jedis.ShardedJedisPool"</span>></span>
        <span style="color:#006666"><<span style="color:#4f4f4f">constructor-arg</span> <span style="color:#4f4f4f">index</span>=<span style="color:#009900">"0"</span> <span style="color:#4f4f4f">ref</span>=<span style="color:#009900">"jedisPoolConfig"</span> /></span>
        <span style="color:#006666"><<span style="color:#4f4f4f">constructor-arg</span> <span style="color:#4f4f4f">index</span>=<span style="color:#009900">"1"</span>></span>
            <span style="color:#006666"><<span style="color:#4f4f4f">list</span>></span>
                <span style="color:#006666"><<span style="color:#4f4f4f">bean</span> <span style="color:#4f4f4f">class</span>=<span style="color:#009900">"redis.clients.jedis.JedisShardInfo"</span>></span>
                    <span style="color:#006666"><<span style="color:#4f4f4f">constructor-arg</span> <span style="color:#4f4f4f">index</span>=<span style="color:#009900">"0"</span> <span style="color:#4f4f4f">value</span>=<span style="color:#009900">"${redis.uri.0}"</span> /></span>
                <span style="color:#006666"></<span style="color:#4f4f4f">bean</span>></span>
            <span style="color:#006666"></<span style="color:#4f4f4f">list</span>></span>
        <span style="color:#006666"></<span style="color:#4f4f4f">constructor-arg</span>></span>
    <span style="color:#006666"></<span style="color:#4f4f4f">bean</span>></span>

<span style="color:#006666"></<span style="color:#4f4f4f">beans</span>></span></code></span>

几个注意的点:

(1)如果你有多个数据源需要通过<context:property-placeholder>管理,且不愿意放在一个配置文件里,那么一定要加上ignore-unresolvable=“true”

(2)注意新版的(具体从哪个版本开始不清楚,有兴趣可以查一下)JedisPoolConfig的property name,不是maxActive而是maxTotal,而且没有maxWait属性,建议看一下Jedis源码。

(3)ShardedJedisPool有多种构造函数,选择你需要的(具体看源码),示例中只初始化了一个分片,并使用了通过指定host的构造器(具体格式见下文),如果有集群,在下增加新的即可。

(4)当然,你的spring核心配置文件中得有扫描组件。

(5)客户端分片使用ShardedJedisPool,设置DB和超时时间

redis连接池配置文件spring-redis.properties

<span style="color:#000000"><code><span style="color:#009900">#最大分配的对象数</span>
redis<span style="color:#009900">.pool</span><span style="color:#009900">.maxActive</span>=<span style="color:#006666">10</span>
<span style="color:#009900">#最大能够保持idel状态的对象数  </span>
redis<span style="color:#009900">.pool</span><span style="color:#009900">.maxIdle</span>=<span style="color:#006666">10</span>
<span style="color:#009900">#最小空闲的对象数。2.5.1以上版本有效</span>
redis<span style="color:#009900">.pool</span><span style="color:#009900">.minIdle</span>=<span style="color:#006666">8</span>
<span style="color:#009900">#当池内没有返回对象时,最大等待时间</span>
redis<span style="color:#009900">.pool</span><span style="color:#009900">.maxWait</span>=<span style="color:#006666">1000</span>
<span style="color:#009900">#是否启用Lifo。如果不设置,默认为true。2.5.1以上版本有效</span>
redis<span style="color:#009900">.pool</span><span style="color:#009900">.lifo</span>=false
<span style="color:#009900">#当调用borrow Object方法时,是否进行有效性检查  </span>
redis<span style="color:#009900">.pool</span><span style="color:#009900">.testOnBorrow</span>=false

<span style="color:#009900">## REDIS URI</span>
<span style="color:#009900">## 使用DB0库</span>
<span style="color:#009900">##redis://用户名:密码@host:port/库,其中用户名随意填写的</span>
redis<span style="color:#009900">.uri</span><span style="color:#006666">.0</span>=redis://testRedis:foobared@119<span style="color:#006666">.254</span><span style="color:#006666">.166</span><span style="color:#006666">.136</span>:<span style="color:#006666">6379</span>/<span style="color:#006666">0</span></code></span>

注意:redis uir的格式为 redis://用户名:密码@host:port/库,其中用户名随意填写的,如果没有用户名和密码,格式为redis://:@host:port/库,使用这种方式,配置内容少,还能自定义db index,非常适合开发、测试和线上环境的切换

代码实现

(1)推荐大家使用统一的类来管理Jedis实例的生成和回收,参考代码如下:JedisDataSourceImpl

<span style="color:#000000"><code><span style="color:#9b859d">@Repository</span>(<span style="color:#009900">"jedisDS"</span>)
<span style="color:#000088">public</span> <span style="color:#000088">class</span> <span style="color:#4f4f4f">JedisDataSourceImpl</span> <span style="color:#000088">implements</span> <span style="color:#4f4f4f">JedisDataSource</span> {
    <span style="color:#000088">private</span> <span style="color:#000088">static</span> <span style="color:#000088">final</span> Logger LOG = LoggerFactory.getLogger(JedisDataSourceImpl.class);

    <span style="color:#9b859d">@Autowired</span>
    <span style="color:#000088">private</span> ShardedJedisPool shardedJedisPool;

    <span style="color:#9b859d">@Override</span>
    <span style="color:#000088">public</span> ShardedJedis <span style="color:#009900">getRedisClient</span>() {
        ShardedJedis shardJedis = <span style="color:#000088">null</span>;
        <span style="color:#000088">try</span> {
            shardJedis = shardedJedisPool.getResource();
            <span style="color:#000088">return</span> shardJedis;
        } <span style="color:#000088">catch</span> (Exception e) {
            LOG.error(<span style="color:#009900">"[JedisDS] getRedisClent error:"</span> + e.getMessage());
            <span style="color:#000088">if</span> (<span style="color:#000088">null</span> != shardJedis)
                shardJedis.close();
        }
        <span style="color:#000088">return</span> <span style="color:#000088">null</span>;
    }

    <span style="color:#9b859d">@Override</span>
    <span style="color:#000088">public</span> <span style="color:#000088">void</span> <span style="color:#009900">returnResource</span>(ShardedJedis shardedJedis) {
        shardedJedis.close();
    }

    <span style="color:#9b859d">@Override</span>
    <span style="color:#000088">public</span> <span style="color:#000088">void</span> <span style="color:#009900">returnResource</span>(ShardedJedis shardedJedis, <span style="color:#000088">boolean</span> broken) {
        shardedJedis.close();
    }

}</code></span>

这里要注意的是Jedis实例的回收,从jedis2.6开始,原returnResource方式已经提示在后续版本中不再支持,所以不建议大家再用ShardedJedisPool里的returnResource和retureBrokenResource方法,虽然在2.7中还支持(毕竟是因为这两个方法存在漏洞)。

(2)编写具体的Jedis操作类(片断):RedisClientTemplate

<span style="color:#000000"><code><span style="color:#9b859d">@Repository</span>(<span style="color:#009900">"redisClientTemplate"</span>)
<span style="color:#000088">public</span> <span style="color:#000088">class</span> <span style="color:#4f4f4f">RedisClientTemplate</span> {
    <span style="color:#000088">private</span> <span style="color:#000088">static</span> <span style="color:#000088">final</span> Logger log = LoggerFactory.getLogger(RedisClientTemplate.class);

    <span style="color:#9b859d">@Autowired</span>
    <span style="color:#000088">private</span> JedisDataSource redisDataSource;

    <span style="color:#000088">public</span> <span style="color:#000088">void</span> <span style="color:#009900">disconnect</span>() {
        ShardedJedis shardedJedis = redisDataSource.getRedisClient();
        shardedJedis.disconnect();
    }

    <span style="color:#880000">/**
     * 设置单个值
     * 
     *<span style="color:#4f4f4f"> @param</span> key
     *<span style="color:#4f4f4f"> @param</span> value
     *<span style="color:#4f4f4f"> @return</span>
     */</span>
    <span style="color:#000088">public</span> String <span style="color:#009900">set</span>(String key, String value) {
        String result = <span style="color:#000088">null</span>;

        ShardedJedis shardedJedis = redisDataSource.getRedisClient();
        <span style="color:#000088">if</span> (shardedJedis == <span style="color:#000088">null</span>) {
            <span style="color:#000088">return</span> result;
        }
        <span style="color:#000088">boolean</span> broken = <span style="color:#000088">false</span>;
        <span style="color:#000088">try</span> {
            result = shardedJedis.set(key, value);
        } <span style="color:#000088">catch</span> (Exception e) {
            log.error(e.getMessage(), e);
            broken = <span style="color:#000088">true</span>;
        } <span style="color:#000088">finally</span> {
            redisDataSource.returnResource(shardedJedis, broken);
        }
        <span style="color:#000088">return</span> result;
    }

    <span style="color:#880000">/**
     * 获取单个值
     * 
     *<span style="color:#4f4f4f"> @param</span> key
     *<span style="color:#4f4f4f"> @return</span>
     */</span>
    <span style="color:#000088">public</span> String <span style="color:#009900">get</span>(String key) {
        String result = <span style="color:#000088">null</span>;
        ShardedJedis shardedJedis = redisDataSource.getRedisClient();
        <span style="color:#000088">if</span> (shardedJedis == <span style="color:#000088">null</span>) {
            <span style="color:#000088">return</span> result;
        }

        <span style="color:#000088">boolean</span> broken = <span style="color:#000088">false</span>;
        <span style="color:#000088">try</span> {
            result = shardedJedis.get(key);

        } <span style="color:#000088">catch</span> (Exception e) {
            log.error(e.getMessage(), e);
            broken = <span style="color:#000088">true</span>;
        } <span style="color:#000088">finally</span> {
            redisDataSource.returnResource(shardedJedis, broken);
        }
        <span style="color:#000088">return</span> result;
    }

    <span style="color:#000088">public</span> Boolean <span style="color:#009900">exists</span>(String key) {
        Boolean result = <span style="color:#000088">false</span>;
        ShardedJedis shardedJedis = redisDataSource.getRedisClient();
        <span style="color:#000088">if</span> (shardedJedis == <span style="color:#000088">null</span>) {
            <span style="color:#000088">return</span> result;
        }
        <span style="color:#000088">boolean</span> broken = <span style="color:#000088">false</span>;
        <span style="color:#000088">try</span> {
            result = shardedJedis.exists(key);
        } <span style="color:#000088">catch</span> (Exception e) {
            log.error(e.getMessage(), e);
            broken = <span style="color:#000088">true</span>;
        } <span style="color:#000088">finally</span> {
            redisDataSource.returnResource(shardedJedis, broken);
        }
        <span style="color:#000088">return</span> result;
    }

    <span style="color:#000088">public</span> String <span style="color:#009900">type</span>(String key) {
        String result = <span style="color:#000088">null</span>;
        ShardedJedis shardedJedis = redisDataSource.getRedisClient();
        <span style="color:#000088">if</span> (shardedJedis == <span style="color:#000088">null</span>) {
            <span style="color:#000088">return</span> result;
        }
        <span style="color:#000088">boolean</span> broken = <span style="color:#000088">false</span>;
        <span style="color:#000088">try</span> {
            result = shardedJedis.type(key);

        } <span style="color:#000088">catch</span> (Exception e) {
            log.error(e.getMessage(), e);
            broken = <span style="color:#000088">true</span>;
        } <span style="color:#000088">finally</span> {
            redisDataSource.returnResource(shardedJedis, broken);
        }
        <span style="color:#000088">return</span> result;
    }

    <span style="color:#880000">/**
     * 在某段时间后失效
     * 
     *<span style="color:#4f4f4f"> @param</span> key
     *<span style="color:#4f4f4f"> @param</span> seconds
     *<span style="color:#4f4f4f"> @return</span>
     */</span>
    <span style="color:#000088">public</span> Long <span style="color:#009900">expire</span>(String key, <span style="color:#000088">int</span> seconds) {
        Long result = <span style="color:#000088">null</span>;
        ShardedJedis shardedJedis = redisDataSource.getRedisClient();
        <span style="color:#000088">if</span> (shardedJedis == <span style="color:#000088">null</span>) {
            <span style="color:#000088">return</span> result;
        }
        <span style="color:#000088">boolean</span> broken = <span style="color:#000088">false</span>;
        <span style="color:#000088">try</span> {
            result = shardedJedis.expire(key, seconds);

        } <span style="color:#000088">catch</span> (Exception e) {
            log.error(e.getMessage(), e);
            broken = <span style="color:#000088">true</span>;
        } <span style="color:#000088">finally</span> {
            redisDataSource.returnResource(shardedJedis, broken);
        }
        <span style="color:#000088">return</span> result;
    }

    <span style="color:#880000">/**
     * 在某个时间点失效
     * 
     *<span style="color:#4f4f4f"> @param</span> key
     *<span style="color:#4f4f4f"> @param</span> unixTime
     *<span style="color:#4f4f4f"> @return</span>
     */</span>
    <span style="color:#000088">public</span> Long <span style="color:#009900">expireAt</span>(String key, <span style="color:#000088">long</span> unixTime) {
        Long result = <span style="color:#000088">null</span>;
        ShardedJedis shardedJedis = redisDataSource.getRedisClient();
        <span style="color:#000088">if</span> (shardedJedis == <span style="color:#000088">null</span>) {
            <span style="color:#000088">return</span> result;
        }
        <span style="color:#000088">boolean</span> broken = <span style="color:#000088">false</span>;
        <span style="color:#000088">try</span> {
            result = shardedJedis.expireAt(key, unixTime);

        } <span style="color:#000088">catch</span> (Exception e) {
            log.error(e.getMessage(), e);
            broken = <span style="color:#000088">true</span>;
        } <span style="color:#000088">finally</span> {
            redisDataSource.returnResource(shardedJedis, broken);
        }
        <span style="color:#000088">return</span> result;
    }

    <span style="color:#000088">public</span> Long <span style="color:#009900">ttl</span>(String key) {
        Long result = <span style="color:#000088">null</span>;
        ShardedJedis shardedJedis = redisDataSource.getRedisClient();
        <span style="color:#000088">if</span> (shardedJedis == <span style="color:#000088">null</span>) {
            <span style="color:#000088">return</span> result;
        }
        <span style="color:#000088">boolean</span> broken = <span style="color:#000088">false</span>;
        <span style="color:#000088">try</span> {
            result = shardedJedis.ttl(key);

        } <span style="color:#000088">catch</span> (Exception e) {
            log.error(e.getMessage(), e);
            broken = <span style="color:#000088">true</span>;
        } <span style="color:#000088">finally</span> {
            redisDataSource.returnResource(shardedJedis, broken);
        }
        <span style="color:#000088">return</span> result;
    }

    <span style="color:#000088">public</span> <span style="color:#000088">boolean</span> <span style="color:#009900">setbit</span>(String key, <span style="color:#000088">long</span> offset, <span style="color:#000088">boolean</span> value) {

        ShardedJedis shardedJedis = redisDataSource.getRedisClient();
        <span style="color:#000088">boolean</span> result = <span style="color:#000088">false</span>;
        <span style="color:#000088">if</span> (shardedJedis == <span style="color:#000088">null</span>) {
            <span style="color:#000088">return</span> result;
        }
        <span style="color:#000088">boolean</span> broken = <span style="color:#000088">false</span>;
        <span style="color:#000088">try</span> {
            result = shardedJedis.setbit(key, offset, value);
        } <span style="color:#000088">catch</span> (Exception e) {
            log.error(e.getMessage(), e);
            broken = <span style="color:#000088">true</span>;
        } <span style="color:#000088">finally</span> {
            redisDataSource.returnResource(shardedJedis, broken);
        }
        <span style="color:#000088">return</span> result;
    }

    <span style="color:#000088">public</span> <span style="color:#000088">boolean</span> <span style="color:#009900">getbit</span>(String key, <span style="color:#000088">long</span> offset) {
        ShardedJedis shardedJedis = redisDataSource.getRedisClient();
        <span style="color:#000088">boolean</span> result = <span style="color:#000088">false</span>;
        <span style="color:#000088">if</span> (shardedJedis == <span style="color:#000088">null</span>) {
            <span style="color:#000088">return</span> result;
        }
        <span style="color:#000088">boolean</span> broken = <span style="color:#000088">false</span>;

        <span style="color:#000088">try</span> {
            result = shardedJedis.getbit(key, offset);
        } <span style="color:#000088">catch</span> (Exception e) {
            log.error(e.getMessage(), e);
            broken = <span style="color:#000088">true</span>;
        } <span style="color:#000088">finally</span> {
            redisDataSource.returnResource(shardedJedis, broken);
        }
        <span style="color:#000088">return</span> result;
    }

    <span style="color:#000088">public</span> <span style="color:#000088">long</span> <span style="color:#009900">setRange</span>(String key, <span style="color:#000088">long</span> offset, String value) {
        ShardedJedis shardedJedis = redisDataSource.getRedisClient();
        <span style="color:#000088">long</span> result = <span style="color:#006666">0</span>;
        <span style="color:#000088">if</span> (shardedJedis == <span style="color:#000088">null</span>) {
            <span style="color:#000088">return</span> result;
        }
        <span style="color:#000088">boolean</span> broken = <span style="color:#000088">false</span>;
        <span style="color:#000088">try</span> {
            result = shardedJedis.setrange(key, offset, value);
        } <span style="color:#000088">catch</span> (Exception e) {
            log.error(e.getMessage(), e);
            broken = <span style="color:#000088">true</span>;
        } <span style="color:#000088">finally</span> {
            redisDataSource.returnResource(shardedJedis, broken);
        }
        <span style="color:#000088">return</span> result;
    }

    <span style="color:#000088">public</span> String <span style="color:#009900">getRange</span>(String key, <span style="color:#000088">long</span> startOffset, <span style="color:#000088">long</span> endOffset) {
        ShardedJedis shardedJedis = redisDataSource.getRedisClient();
        String result = <span style="color:#000088">null</span>;
        <span style="color:#000088">if</span> (shardedJedis == <span style="color:#000088">null</span>) {
            <span style="color:#000088">return</span> result;
        }
        <span style="color:#000088">boolean</span> broken = <span style="color:#000088">false</span>;
        <span style="color:#000088">try</span> {
            result = shardedJedis.getrange(key, startOffset, endOffset);

        } <span style="color:#000088">catch</span> (Exception e) {
            log.error(e.getMessage(), e);
            broken = <span style="color:#000088">true</span>;
        } <span style="color:#000088">finally</span> {
            redisDataSource.returnResource(shardedJedis, broken);
        }
        <span style="color:#000088">return</span> result;
    }
}</code></span>

(3)好了,接下来在你的业务代码里加载RedisClientTemplate.class就可以了。

<span style="color:#000000"><code>
<span style="color:#9b859d">@RunWith</span>(SpringJUnit4ClassRunner.class)
<span style="color:#9b859d">@ContextConfiguration</span>(<span style="color:#009900">"classpath:spring-redis.xml"</span>)
<span style="color:#000088">public</span> <span style="color:#000088">class</span> <span style="color:#4f4f4f">RedisTest</span>{
    <span style="color:#9b859d">@Autowired</span>
    <span style="color:#000088">private</span> RedisClientTemplate redisClientTemplate ;

    <span style="color:#9b859d">@Test</span>
    <span style="color:#000088">public</span> <span style="color:#000088">void</span> <span style="color:#009900">testSave</span>(){
        String key = <span style="color:#009900">"10086"</span>;
        String val = <span style="color:#009900">"中国移动"</span>;
        String r = redisClientTemplate .save(key,val);
        System.out.println(r);
    }

    <span style="color:#9b859d">@Test</span>
    <span style="color:#000088">public</span> <span style="color:#000088">void</span> <span style="color:#009900">testFind</span>(){
        String key = <span style="color:#009900">"10086"</span>;
        String result = redisClientTemplate .find(key);
        System.out.println(result);
    }

    <span style="color:#9b859d">@Test</span> <span style="color:#000088">public</span> <span style="color:#000088">void</span> <span style="color:#009900">testDel</span>(){
        String key = <span style="color:#009900">"10086"</span>;
        <span style="color:#000088">long</span> l = redisClientTemplate .delete(key);
        System.out.println(l);
    }
}</code></span>

补充:


1、shardedjedispool分片实现集群与jediscluster实现集群区别以及jediscluster实现集群可以查看 分布式缓存技术redis学习系列(七)——spring整合jediscluster 

2、shardedjedispool分片集群与jediscluster集群同样不具有高可用特性,但基于shardedjedispool的ShardedJedisSentinelPool可以实现集群高可用,redis服务一台master挂机,sentinel哨兵进行主从切换之后,客户端程序自动完成同步的主从切换。 
具体的实现方式就是通过sentinel的sentinelGetMasterAddrByName(masterName);(实际执行sentinel的get-master-addr-by-name命令)获取哨兵监控的所有master节点;然后用一个MasterListener启用一个线程,利用redis的订阅与发布机制,订阅+switch-master频道,时时获取redis服务端主从切换的信息。 
实现原理和源码分析可以查看 基于Redis Sentinel的Redis集群(主从&Sharding)高可用方案 相关源码地址位于 sharded-jedis-sentinel-pool 

 

猜你喜欢

转载自blog.csdn.net/a1ccwt/article/details/81359496
今日推荐