redis分佈式鎖

1:使用redis自帶的分佈式鎖,set px nxmysql

set key 1 px 60000 nx

px 過時時間      nx 分佈式鎖參數,只有當不存在時,纔可設置成功redis

 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 spring

//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 sql

//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的鎖功能)數據庫

相關文章
相關標籤/搜索