Redis学习笔记(七)—— 在Spring框架中实现基于Redis的分布式锁(单机版)

        目前很多大型网站及应用都是分布式部署的,分布式场景中的数据一致性问题一直是一个比较重要的话题。分布式的CAP理论告诉我们:“任何一个分布式系统都无法同时满足一致性(Consistency)、可用性(Availability)和分区容错性(Partition tolerance),最多只能同时满足其中两项”。所以,很多系统在设计之初就要对这三者进行取舍。在互联网领域的绝大多数的场景中,都需要牺牲系统的强一致性来换取系统的高可用性,系统往往只需要保证“最终一致性”,只要这个最终时间在用户的可接受范围之内即可。

        我们为了保证数据的最终一致性,需要很多技术方案来支持,比如分布式事务、分布式锁等。针对分布式锁的实现,目前主要有三种实现方案,一是基于数据库(oracle、mysql)实现分布式锁;二是基于缓存(redis、memcached)实现分布式锁;三是基于Zookeeper实现分布式锁。下面实现的是基于Redis单机版实现的分布式锁,适合并发量不是很大的中小型项目。

一、实现分布式锁所需要的pom依赖

        <spring.version>5.0.0.RELEASE</spring.version>
        <aspectj.version>1.8.11</aspectj.version>
        <jedis.version>2.9.0</jedis.version>
        <spring.data.redis.version>1.6.0.RELEASE</spring.data.redis.version>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-orm</artifactId>
                <version>${spring.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-webmvc</artifactId>
                <version>${spring.version}</version>
            </dependency>
            <dependency>
                <groupId>org.aspectj</groupId>
                <artifactId>aspectjweaver</artifactId>
                <version>${aspectj.version}</version>
            </dependency>        
            <dependency>
                <groupId>redis.clients</groupId>
                <artifactId>jedis</artifactId>
                <version>${jedis.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.data</groupId>
                <artifactId>spring-data-redis</artifactId>
                <version>${spring.data.redis.version}</version>
            </dependency>

二、添加spring测试文件applicationContext-test-redis.xml

此文件添加目录为:src/main/resources/spring/applicationContext-test-redis.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                http://www.springframework.org/schema/beans/spring-beans.xsd
                http://www.springframework.org/schema/context
                http://www.springframework.org/schema/context/spring-context.xsd">
    <!-- 配置扫描器,指定要扫描哪个包下面的注解类 -->
    <context:component-scan base-package="com.mengfei.redis"/>

    <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <property name="maxIdle" value="300" />
        <property name="maxTotal" value="600" />
        <property name="maxWaitMillis" value="1000" />
        <property name="testOnBorrow" value="true" />
    </bean>

    <!-- 配置JedisConnectionFactory -->
    <bean id="jedisConnectionFactory" 
class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
        <property name="hostName" value="localhost" />
        <property name="port" value="6379" />
        <!-- <property name="password" value="${redis.pass}" /> -->
        <property name="database" value="0" />
        <property name="poolConfig" ref="poolConfig" />
    </bean>

    <bean id="jedisTest" class="com.mengfei.redis.JedisTest">
        <property name="jedisConnectionFactory" ref="jedisConnectionFactory"/>
    </bean>
</beans>

三、添加测试类 JedisTest

@Component
public class JedisTest {

    @Test
    public void example1() {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring/applicationContext-test-redis.xml");
        JedisConnectionFactory jedisConnectionFactory = (JedisConnectionFactory) context.getBean("jedisConnectionFactory");
        Field jedisField = ReflectionUtils.findField(JedisConnection.class, "jedis");
        ReflectionUtils.makeAccessible(jedisField);
        System.out.println(jedisConnectionFactory.getConnection());
        Jedis jedis = (Jedis) ReflectionUtils.getField(jedisField, jedisConnectionFactory.getConnection());
        String result = jedis.set("test-key", "Hello world-", "NX", "EX", 100);
        System.out.println(result);
        //代码执行后,返回字符串”OK”或者”null”,表示是否设值成功。
    }
}

测试成功后就可以在项目中进行代码部署了,示例如下: 

四、实现分布式的工具类



import redis.clients.jedis.Jedis;

import java.util.Collections;

/**
 * author Alex
 * date 2018/01/22
 * description 一个用于获取redis分布式锁的工具类,适用于单机部署的redis
 * Redis如果是多机部署的,那么可以尝试使用Redisson实现分布式锁,这是Redis官方提供的Java组件
 * Redisson的github链接:https://github.com/redisson/redisson
 * Redisson的使用示例链接:https://blog.csdn.net/u014042066/article/details/72778440
 */
public class RedisDistributedLockUtil {

    private static final String LOCK_SUCCESS = "OK";
    private static final Long RELEASE_SUCCESS = 1L;
    //意思是SET IF NOT EXIST,即当key不存在时,我们进行set操作;若key已经存在,则不做任何操作
    private static final String SET_IF_NOT_EXIST = "NX";
    //意思是我们要给这个key加一个过期的设置,具体时间由第五个参数决定
    private static final String SET_WITH_EXPIRE_TIME = "EX";

    /**
     * 获取分布式锁
     * @param jedis Redis客户端
     * @param lockKey 锁的keyName
     * @param requestId 请求标识,可以使用UUID,为了确认在分布式环境下是哪个客户端加的锁,同时也用于解锁
     * @param expireTime 过期时间,单位(秒)
     * @return 是否获取成功
     */
    public static boolean getDistributedLock(Jedis jedis, String lockKey, String requestId, int expireTime) {

        //加锁
        String result = jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime);

        if (LOCK_SUCCESS.equals(result)) {
            return true;
        }
        return false;

    }

    /**
     * 释放分布式锁
     * @param jedis Redis客户端
     * @param lockKey 锁的keyName
     * @param requestId 请求标识,使用加锁时生成的UUID
     * @return 是否释放成功
     */
    public static boolean releaseDistributedLock(Jedis jedis, String lockKey, String requestId) {

        //Lua脚本代码,KEYS[1]使用lockKey参数,ARGV[1]使用requestId参数
        //Lua脚本含义:首先获取锁的value值,看是否与请求的标识相匹配,如果匹配则删除锁,否则就返回0
        //Lua脚本代码在执行时将会被当作一个命令来执行,并且直到eval命令执行完成,才会执行其他命令,它具有原子性
        String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
        //eval()方法是将Lua代码交给Redis服务端执行
        Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId));

        if (RELEASE_SUCCESS.equals(result)) {
            return true;
        }
        return false;

    }
}

五、实现分布式锁的伪代码

@Autowired
private JedisConnectionFactory jedisConnectionFactory;

public void handleService() throws Exception {
        Jedis jedis = null;
        try {
            //通过反射获取Jedis连接对象
            Field jedisField = ReflectionUtils.findField(JedisConnection.class, "jedis");
            //将该字段设置为可访问,主要是针对private字段
            ReflectionUtils.makeAccessible(jedisField);
            jedis = (Jedis) ReflectionUtils.getField(jedisField, jedisConnectionFactory.getConnection());
            //获取请求客户端标识
            String requestId = UUID.randomUUID().toString();
            //设置超时时间
            long timeOut = System.currentTimeMillis() + 3 * 1000;
            //更新缓存数据之前先获取Redis分布式锁,如果获取到Redis分布式锁则进行更新,否则就循环获取锁直到超时
            while (true) {
                //获取分布式锁并设置锁的自动过期时间为2秒
                boolean distributedLock = RedisDistributedLockUtil.getDistributedLock(
                        jedis, RedisKeyNameEnum.TEL_TIP_DISTRIBUTED_LOCK.getFactValue(), requestId, 2);
                if (distributedLock) {
                    //进行业务处理....

                    //处理结束后要释放锁
                    boolean b = RedisDistributedLockUtil.releaseDistributedLock(
                            jedis, RedisKeyNameEnum.TEL_TIP_DISTRIBUTED_LOCK.getFactValue(), requestId);
                    if (b) {
                        System.out.println("成功释放Redis分布式锁!");
                    } else {
                        System.out.println("释放Redis分布式锁失败,等待锁自动超时.........");
                    }
                    //业务处理结束后要中止循环
                    break;
                } else {
                    //超时还未获取到锁则中止循环
                    if (System.currentTimeMillis() > timeOut) {
                        System.out.println("获取Redis分布式锁超时,可能是连接异常,循环中止..........");
                        break;
                    }
                    System.out.println("获取Redis分布式锁失败,休眠100毫秒再重新尝试获取锁,休眠中..........");
                    //获取分布式锁失败休眠100毫秒再重新获取锁
                    Thread.sleep(100);
                }
            }
        } finally {
            //异常抛给上层应用去处理,这里只进行关闭资源的操作处理
            if (null != jedis) {
                jedis.close();
            }
        }
    }

六、项目中配置Redis的缓存管理器

<!-- 配置JedisPoolConfig实例 -->
    <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <property name="maxIdle" value="300" />
        <property name="maxTotal" value="600" />
        <property name="maxWaitMillis" value="1000" />
        <property name="testOnBorrow" value="true" />
    </bean>

    <!-- 配置JedisConnectionFactory -->
    <bean id="jedisConnectionFactory"
        class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
        <property name="hostName" value="localhost" />
        <property name="port" value="6379" />
        <!-- <property name="password" value="${redis.pass}" /> -->
        <property name="database" value="0" />
        <property name="poolConfig" ref="poolConfig" />
    </bean>

    <!-- 配置RedisTemplate -->
    <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
        <property name="connectionFactory" ref="jedisConnectionFactory" />
    </bean>

    <!-- 配置RedisCacheManager -->
    <bean id="redisCacheManager" class="org.springframework.data.redis.cache.RedisCacheManager">
        <constructor-arg name="redisOperations" ref="redisTemplate" />
        <property name="defaultExpiration" value="3000" />
    </bean>

    <!-- 配置RedisCacheConfig 下面的RedisUtil是进行业务操作的工具类-->
    <bean id="redisUtil" class="com.mengfei.redis.RedisUtil">
         <property name="redisTemplate" ref="redisTemplate" />
    </bean>

七、进行redis业务操作的工具类RedisUtil

 

package com.mengfei.redis;

import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.concurrent.TimeUnit;

public class RedisUtil {

private RedisTemplate<String, Object> redisTemplate;

    public void setRedisTemplate(RedisTemplate<String, Object> redisTemplate) {
    	RedisSerializer redisSerializer = new JdkSerializationRedisSerializer();
    	RedisSerializer redisSerializerString = new StringRedisSerializer();
        redisTemplate.setKeySerializer(redisSerializerString);
        redisTemplate.setValueSerializer(redisSerializer);
        this.redisTemplate = redisTemplate;  
    }  
    
    public RedisTemplate<String, Object> getRedisTemplate() {
		return redisTemplate;
	}

	//=============================common============================  
    
    public Set<String> getKeys(String key){
    	if(key == null || "".equals(key)){
    		return null;
    	}
    
    	Set<String> r = redisTemplate.keys(key);
    	return r;
    }
    /**
     * 批量获取redis string
     * @param keys
     * @return
     */
    public List<Object> batchGetString(Collection<String> keys ){
    	if(CollectionUtils.isEmpty(keys)){
    		return null;
    	}
    	 RedisSerializer<String> serializer = redisTemplate.getStringSerializer();
    	List<Object> r =redisTemplate.executePipelined(new RedisCallback<Object>() {
    	    public Object doInRedis(RedisConnection connection) throws DataAccessException {
    	    	 byte[][] rawKeys = new byte[keys.size()][]; 
    	        Iterator<String> it = keys.iterator() ;     
    	        int i = 0;
		        while(it.hasNext()){    
		        	String key = it.next();
//		        	return jdkSerializer.deserialize(connection.get(serializer.serialize(key)));
//		        	connection.rPop(serializer.serialize(key));
		        	rawKeys[i++] = serializer.serialize(key);
		        	connection.get(serializer.serialize(key));
    	        }
//		        connection.mGet(rawKeys);
    	      return null;
    	    }
    	  });
    	return r;
    }
    /**
     * 批量插入 redis string
     * @param list
     */
    public boolean batchSetString(List<Map<String,String>> list) {
    	 boolean result = redisTemplate.execute(new RedisCallback<Boolean>() {
             public Boolean doInRedis(RedisConnection connection)
                     throws DataAccessException {
                 RedisSerializer<String> serializer = redisTemplate.getStringSerializer();
                 for (Map<String, String> map : list) {
                	 Set<String> key = map.keySet();
                	 Iterator<String> it = key.iterator();
                	 while(it.hasNext()) {
                		 String inner = it.next();
                		  byte[] innerKey  = serializer.serialize(inner);
                          byte[] name = serializer.serialize(map.get(inner));
                          connection.setNX(innerKey, name);
                	 }
                   
                 }
                 return true;
             }
         }, false, true);
         return result;
    }
    
    /**
     * 批量插入 redis string
     * @param list
     */
    public boolean batchSetHash(List<Map<String,String>> list,String key) {
    	 boolean result = redisTemplate.execute(new RedisCallback<Boolean>() {
             public Boolean doInRedis(RedisConnection connection)
                     throws DataAccessException {
                 RedisSerializer<String> serializer = redisTemplate.getStringSerializer();
                 byte[] keyByte = serializer.serialize(key);
                 for (Map<String, String> map : list) {
                	 Set<String> key = map.keySet();
                	 Iterator<String> it = key.iterator();
                	 while(it.hasNext()) {
                		 String inner = it.next();
                		  byte[] innerKey  = serializer.serialize(inner);
                          byte[] name = serializer.serialize(map.get(inner));
                          connection.hSet(keyByte, innerKey, name);
                	 }
                   
                 }
                 return true;
             }
         }, false, true);
         return result;
    }
    
    /**
     * get cache
     *
     * @param field
     * @return
     */
    public byte[] getByte(String field) {
        byte[] result = redisTemplate.execute((RedisCallback<byte[]>) 
connection -> connection.get(field.getBytes()));
        if (result == null) {
            return null;
        }
        return result;
    }


    /** 
     * 指定缓存失效时间 
     * @param key 键 
     * @param time 时间(秒) 
     * @return 
     */  
    public boolean expire(String key,long time){  
        try {  
            if(time>0){  
                redisTemplate.expire(key, time, TimeUnit.SECONDS);  
            }  
            return true;  
        } catch (Exception e) {  
            e.printStackTrace();  
            return false;  
        }  
    }  

    /** 
     * 根据key 获取过期时间 
     * @param key 键 不能为null 
     * @return 时间(秒) 返回0代表为永久有效 
     */  
    public long getExpire(String key){  
        return redisTemplate.getExpire(key,TimeUnit.SECONDS);  
    }  

    /** 
     * 判断key是否存在 
     * @param key 键 
     * @return true 存在 false不存在 
     */  
    public boolean hasKey(String key){  
        try {  
            return redisTemplate.hasKey(key);  
        } catch (Exception e) {  
            e.printStackTrace();  
            return false;  
        }  
    }  

    /** 
     * 删除缓存 
     * @param key 可以传一个值 或多个 
     */  
    @SuppressWarnings("unchecked")  
    public void del(String ... key){  
        if(key!=null&&key.length>0){  
            if(key.length==1){  
                redisTemplate.delete(key[0]);  
            }else{  
                redisTemplate.delete(CollectionUtils.arrayToList(key));
            }  
        }  
    }  

    //============================String=============================  
    /** 
     * 普通缓存获取 
     * @param key 键 
     * @return 值 
     */  
    public Object get(String key){  
        return key==null?null:redisTemplate.opsForValue().get(key);  
    }  

    /** 
     * 普通缓存放入 
     * @param key 键 
     * @param value 值 
     * @return true成功 false失败 
     */  
    public boolean set(String key,Object value) {  
         try {  
            redisTemplate.opsForValue().set(key, value);  
            return true;  
        } catch (Exception e) {  
            e.printStackTrace();  
            return false;  
        }  

    }  

    /** 
     * 普通缓存放入并设置时间 
     * @param key 键 
     * @param value 值 
     * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 
     * @return true成功 false 失败 
     */  
    public boolean set(String key,Object value,long time){  
        try {  
            if(time>0){  
                redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);  
            }else{  
                set(key, value);  
            }  
            return true;  
        } catch (Exception e) {  
            e.printStackTrace();  
            return false;  
        }  
    }  

    /** 
     * 递增 
     * @param key 键 
     * @return
     */  
    public long incr(String key, long delta){    
        if(delta<0){  
            throw new RuntimeException("递增因子必须大于0");  
        }  
        return redisTemplate.opsForValue().increment(key, delta);  
    }  

    /** 
     * 递减 
     * @param key 键 
     * @return
     */  
    public long decr(String key, long delta){    
        if(delta<0){  
            throw new RuntimeException("递减因子必须大于0");  
        }  
        return redisTemplate.opsForValue().increment(key, -delta);    
    }    

    //================================Map=================================  
    /** 
     * HashGet 
     * @param key 键 不能为null 
     * @param item 项 不能为null 
     * @return 值 
     */  
    public Object hget(String key,String item){  
        return redisTemplate.opsForHash().get(key, item);  
    }  

    /** 
     * 获取hashKey对应的所有键值 
     * @param key 键 
     * @return 对应的多个键值 
     */  
    public Map<Object,Object> hmget(String key){  
        return redisTemplate.opsForHash().entries(key);  
    }  

    /** 
     * HashSet 
     * @param key 键 
     * @param map 对应多个键值 
     * @return true 成功 false 失败 
     */  
    public boolean hmset(String key, Map<String,Object> map){    
        try {  
            redisTemplate.opsForHash().putAll(key, map);  
            return true;  
        } catch (Exception e) {  
            e.printStackTrace();  
            return false;  
        }  
    }  

    /** 
     * HashSet 并设置时间 
     * @param key 键 
     * @param map 对应多个键值 
     * @param time 时间(秒) 
     * @return true成功 false失败 
     */  
    public boolean hmset(String key, Map<String,Object> map, long time){    
        try {  
            redisTemplate.opsForHash().putAll(key, map);  
            if(time>0){  
                expire(key, time);  
            }  
            return true;  
        } catch (Exception e) {  
            e.printStackTrace();  
            return false;  
        }  
    }  

    /** 
     * 向一张hash表中放入数据,如果不存在将创建 
     * @param key 键 
     * @param item 项 
     * @param value 值 
     * @return true 成功 false失败 
     */  
    public boolean hset(String key,String item,Object value) {  
         try {  
            redisTemplate.opsForHash().put(key, item, value);  
            return true;  
        } catch (Exception e) {  
            e.printStackTrace();  
            return false;  
        }  
    }  

    /** 
     * 向一张hash表中放入数据,如果不存在将创建 
     * @param key 键 
     * @param item 项 
     * @param value 值 
     * @param time 时间(秒)  注意:如果已存在的hash表有时间,这里将会替换原有的时间 
     * @return true 成功 false失败 
     */  
    public boolean hset(String key,String item,Object value,long time) {  
         try {  
            redisTemplate.opsForHash().put(key, item, value);  
            if(time>0){  
                expire(key, time);  
            }  
            return true;  
        } catch (Exception e) {  
            e.printStackTrace();  
            return false;  
        }  
    }  

    /** 
     * 删除hash表中的值 
     * @param key 键 不能为null 
     * @param item 项 可以使多个 不能为null 
     */  
    public void hdel(String key, Object... item){    
        redisTemplate.opsForHash().delete(key,item);  
    }   

    /** 
     * 判断hash表中是否有该项的值 
     * @param key 键 不能为null 
     * @param item 项 不能为null 
     * @return true 存在 false不存在 
     */  
    public boolean hHasKey(String key, String item){  
        return redisTemplate.opsForHash().hasKey(key, item);  
    }   

    /** 
     * hash递增 如果不存在,就会创建一个 并把新增后的值返回 
     * @param key 键 
     * @param item 项 
     * @param by 要增加几(大于0) 
     * @return 
     */  
    public double hincr(String key, String item,double by){    
        return redisTemplate.opsForHash().increment(key, item, by);  
    }  

    /** 
     * hash递减 
     * @param key 键 
     * @param item 项 
     * @param by 要减少记(小于0) 
     * @return 
     */  
    public double hdecr(String key, String item,double by){    
        return redisTemplate.opsForHash().increment(key, item,-by);    
    }    

    //============================set=============================  
    /** 
     * 根据key获取Set中的所有值 
     * @param key 键 
     * @return 
     */  
    public Set<Object> sGet(String key){  
        try {  
            return redisTemplate.opsForSet().members(key);  
        } catch (Exception e) {  
            e.printStackTrace();  
            return null;  
        }  
    }  

    /** 
     * 根据value从一个set中查询,是否存在 
     * @param key 键 
     * @param value 值 
     * @return true 存在 false不存在 
     */  
    public boolean sHasKey(String key,Object value){  
        try {  
            return redisTemplate.opsForSet().isMember(key, value);  
        } catch (Exception e) {  
            e.printStackTrace();  
            return false;  
        }  
    }  

    /** 
     * 将数据放入set缓存 
     * @param key 键 
     * @param values 值 可以是多个 
     * @return 成功个数 
     */  
    public long sSet(String key, Object...values) {  
        try {  
            return redisTemplate.opsForSet().add(key, values);  
        } catch (Exception e) {  
            e.printStackTrace();  
            return 0;  
        }  
    }  

    /** 
     * 将set数据放入缓存 
     * @param key 键 
     * @param time 时间(秒) 
     * @param values 值 可以是多个 
     * @return 成功个数 
     */  
    public long sSetAndTime(String key,long time,Object...values) {  
        try {  
            Long count = redisTemplate.opsForSet().add(key, values);  
            if(time>0) expire(key, time);  
            return count;  
        } catch (Exception e) {  
            e.printStackTrace();  
            return 0;  
        }  
    }  

    /** 
     * 获取set缓存的长度 
     * @param key 键 
     * @return 
     */  
    public long sGetSetSize(String key){  
        try {  
            return redisTemplate.opsForSet().size(key);  
        } catch (Exception e) {  
            e.printStackTrace();  
            return 0;  
        }  
    }  

    /** 
     * 移除值为value的 
     * @param key 键 
     * @param values 值 可以是多个 
     * @return 移除的个数 
     */  
    public long setRemove(String key, Object ...values) {  
        try {  
            Long count = redisTemplate.opsForSet().remove(key, values);  
            return count;  
        } catch (Exception e) {  
            e.printStackTrace();  
            return 0;  
        }  
    }  
    //===============================list=================================  

    /** 
     * 获取list缓存的内容 
     * @param key 键 
     * @param start 开始 
     * @param end 结束  0 到 -1代表所有值 
     * @return 
     */  
    public List<Object> lGet(String key,long start, long end){  
        try {  
            return redisTemplate.opsForList().range(key, start, end);  
        } catch (Exception e) {  
            e.printStackTrace();  
            return null;  
        }  
    }  

    /** 
     * 获取list缓存的长度 
     * @param key 键 
     * @return 
     */  
    public long lGetListSize(String key){  
        try {  
            return redisTemplate.opsForList().size(key);  
        } catch (Exception e) {  
            e.printStackTrace();  
            return 0;  
        }  
    }  

    /** 
     * 通过索引 获取list中的值 
     * @param key 键 
     * @param index 索引  index>=0时, 0 表头,1 第二个元素,依次类推;
index<0时,-1,表尾,-2倒数第二个元素,依次类推 
     * @return 
     */  
    public Object lGetIndex(String key,long index){  
        try {  
            return redisTemplate.opsForList().index(key, index);  
        } catch (Exception e) {  
            e.printStackTrace();  
            return null;  
        }  
    }  

    /** 
     * 将list放入缓存 
     * @param key 键 
     * @param value 值 
     * @return
     */  
    public boolean lSet(String key, Object value) {  
        try {  
            redisTemplate.opsForList().rightPush(key, value);  
            return true;  
        } catch (Exception e) {  
            e.printStackTrace();  
            return false;  
        }  
    }  

    /** 
     * 将list放入缓存 
     * @param key 键 
     * @param value 值 
     * @param time 时间(秒) 
     * @return 
     */  
    public boolean lSet(String key, Object value, long time) {  
        try {  
            redisTemplate.opsForList().rightPush(key, value);  
            if (time > 0) expire(key, time);  
            return true;  
        } catch (Exception e) {  
            e.printStackTrace();  
            return false;  
        }  
    }  

    /** 
     * 将list放入缓存 
     * @param key 键 
     * @param value 值 
     * @return
     */  
    public boolean lSet(String key, List<Object> value) {  
        try {  
            redisTemplate.opsForList().rightPushAll(key, value);  
            return true;  
        } catch (Exception e) {  
            e.printStackTrace();  
            return false;  
        }  
    }  

    /** 
     * 将list放入缓存 
     * @param key 键 
     * @param value 值 
     * @param time 时间(秒) 
     * @return 
     */  
    public boolean lSet(String key, List<Object> value, long time) {  
        try {  
            redisTemplate.opsForList().rightPushAll(key, value);  
            if (time > 0) expire(key, time);  
            return true;  
        } catch (Exception e) {  
            e.printStackTrace();  
            return false;  
        }  
    }

    /**
     *
     * 功能描述: 值左入列
     *
     * @param: 
     * @return: 
     * @auther: Tian
     * @date: 2018/9/20 14:50
     */
    public boolean lLPush(String key, Object value) {
        try {
            redisTemplate.opsForList().leftPush(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     *
     * 功能描述: 值左入列  并设置超时时间
     *
     * @param: 
     * @return: 
     * @auther: Tian
     * @date: 2018/9/20 14:51
     */
    public boolean lLPush(String key, Object value, long time) {
        try {
            redisTemplate.opsForList().leftPush(key, value);
            if (time > 0) expire(key, time);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
    /**
     *
     * 功能描述: 左入列
     *
     * @param:
     * @return:
     * @auther: Tian
     * @date: 2018/9/20 14:47
     */
    public boolean lLPush(String key, List<Object> value) {
        try {
            redisTemplate.opsForList().leftPushAll(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     *
     * 功能描述: 左入列  带超时时间
     *
     * @param:
     * @return:
     * @auther: Tian
     * @date: 2018/9/20 14:48
     */
    public boolean lLPush(String key, List<Object> value, long time) {
        try {
            redisTemplate.opsForList().leftPushAll(key, value);
            if (time > 0) expire(key, time);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
    /**
     *
     * 功能描述: 右出队列
     *
     * @param: [key, value, time]
     * @return: boolean
     * @auther: Tian
     * @date: 2018/9/20 14:52
     */
    public Object lRPop(String key) {
        try {
           return redisTemplate.opsForList().rightPop(key);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
    /**
     *
     * 功能描述: 右出队列
     *
     * @param: [key, value, time]
     * @return: boolean
     * @auther: Tian
     * @date: 2018/9/20 14:52
     */
    public Object lLPop(String key) {
        try {
           return  redisTemplate.opsForList().leftPop(key);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }

    }


    /** 
     * 根据索引修改list中的某条数据 
     * @param key 键 
     * @param index 索引 
     * @param value 值 
     * @return 
     */  
    public boolean lUpdateIndex(String key, long index,Object value) {  
        try {  
            redisTemplate.opsForList().set(key, index, value);  
            return true;  
        } catch (Exception e) {  
            e.printStackTrace();  
            return false;  
        }  
    }   

    /** 
     * 移除N个值为value  
     * @param key 键 
     * @param count 移除多少个 
     * @param value 值 
     * @return 移除的个数 
     */  
    public long lRemove(String key,long count,Object value) {  
        try {  
            Long remove = redisTemplate.opsForList().remove(key, count, value);  
            return remove;  
        } catch (Exception e) {  
            e.printStackTrace();  
            return 0;  
        }  
    }  
    
}

以上示例仅供参考,如有不对的地方,欢迎指正! 

参考:

1、实现基于Redis分布式锁的正确姿势

2、如何从Spring RedisTemplate中获得Jedis实例

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值