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; } }
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; } }
2:redisson框架,一个redis的带有juc的lock功能的客户端的实现(既有jedis的功能,又有juc的锁功能)