redis分布式锁

1:使用redis自带的分布式锁,set px nx

set key 1 px 60000 nx

px 过期时间      nx 分布式锁参数,只有当不存在时,才可设置成功

 public String getUser(String key) {       
        User user = new User();
        // 链接缓存
        Jedis jedis = redisUtil.getJedis();
        // 查询缓存
        String userJson = jedis.get(key);       
        if(StringUtils.isNotBlank(userJson)){//if(userJson!=null&&!userJson.equals(""))           
            user = JSON.parseObject(userJson, User.class);
        }else{ // 如果缓存中没有,查询mysql
            // 设置分布式锁
            String token = UUID.randomUUID().toString();
            String OK = jedis.set(key + ":lock", token, "nx", "px", 10*1000);// 拿到锁的线程有10秒的过期时间
            if(StringUtils.isNotBlank(OK)&&OK.equals("OK")){
                // 设置成功,有权在10秒的过期时间内访问数据库              
                user =  getByIdFromDb(key);
                if(user!=null){
                    // mysql查询结果存入redis
                    jedis.set(key+":info",JSON.toJSONString(user));
                }else{
                    // 数据库中不存在该key
                    // 为了防止缓存穿透将,null或者空字符串值设置给redis
                    jedis.setex(key+":info",60*3,JSON.toJSONString(""));
                }
                // 在访问mysql后,将mysql的分布锁释放
                String lockToken = jedis.get(key + ":lock");
                if(StringUtils.isNotBlank(lockToken)&&lockToken.equals(token)){
                    //jedis.eval("lua");可与用lua脚本,在查询到key的同时删除该key,防止高并发下的意外的发生
                    jedis.del(key + ":lock");// 用token确认删除的是自己的key的锁
                }
            }else{
                // 设置失败,自旋(该线程在睡眠几秒后,重新尝试访问本方法)          
                return getUser(key);
            }
        }
        jedis.close();
        return user;
    }

reids的工具类RedisUtil 

//reids的工具类(用来将redis的池初始化到spring容器中)
public class RedisUtil {
    private  JedisPool jedisPool;
    public void initPool(String host,int port ,int database){
        JedisPoolConfig poolConfig = new JedisPoolConfig();
        poolConfig.setMaxTotal(200);
        poolConfig.setMaxIdle(30);
        poolConfig.setBlockWhenExhausted(true);
        poolConfig.setMaxWaitMillis(10*1000);
        poolConfig.setTestOnBorrow(true);
        jedisPool=new JedisPool(poolConfig,host,port,20*1000);
    }
    public Jedis getJedis(){
        Jedis jedis = jedisPool.getResource();
        return jedis;
    }
}
View Code

redis的配置类RedisConfig 

//spring整合redis的配置类 将redis的链接池创建到spring的容器中
@Configuration
public class RedisConfig {
    //读取配置文件中的redis的ip地址
    @Value("${spring.redis.host:disabled}")
    private String host;
    @Value("${spring.redis.port:0}")
    private int port ;
    @Value("${spring.redis.database:0}")
    private int database;
    @Bean
    public RedisUtil getRedisUtil(){
        if(host.equals("disabled")){
            return null;
        }
        RedisUtil redisUtil=new RedisUtil();
        redisUtil.initPool(host,port,database);
        return redisUtil;
    }
}
View Code

2:redisson框架,一个redis的带有juclock功能的客户端的实现(既有jedis的功能,又有juc的锁功能)

posted @ 2019-12-09 14:35  馥郁  阅读(795)  评论(0编辑  收藏  举报