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; } }
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; } }
2:redisson框架,一個redis的帶有juc的lock功能的客戶端的實現(既有jedis的功能,又有juc的鎖功能)數據庫