博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
redis实现分布式锁工具类 灰常好用
阅读量:7118 次
发布时间:2019-06-28

本文共 5405 字,大约阅读时间需要 18 分钟。

public interface RedisDistributionLock {    /**        * 加锁成功,返回加锁时间        * @param lockKey        * @param threadName        * @return        */       public long lock(String lockKey, String threadName);             /**        * 解锁, 需要更新加锁时间,判断是否有权限        * @param lockKey        * @param lockValue        * @param threadName        */       public void unlock(String lockKey, long lockValue, String threadName);             /**        * 多服务器集群,使用下面的方法,代替System.currentTimeMillis(),获取redis时间,避免多服务的时间不一致问题!!!        * @return        */       public long currtTimeForRedis(); }
import java.util.concurrent.TimeUnit;import org.slf4j.Logger;import org.slf4j.LoggerFactory;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.StringRedisTemplate;import org.springframework.data.redis.serializer.RedisSerializer;public class RedisLockImpl implements RedisDistributionLock{    //加锁超时时间,单位毫秒, 即:加锁时间内执行完操作,如果未完成会有并发现象       private static final long LOCK_TIMEOUT = 5*1000;             private static final Logger LOG = LoggerFactory.getLogger(RedisLockImpl.class);             private StringRedisTemplate redisTemplate;             public RedisLockImpl(StringRedisTemplate redisTemplate) {         this.redisTemplate = redisTemplate;       }             /**        * 加锁        * 取到锁加锁,取不到锁一直等待知道获得锁        * @param lockKey        * @param threadName        * @return        */      @Override      public synchronized long lock(String lockKey, String threadName) { //        LOG.info(threadName+"开始执行加锁");         while (true){ //循环获取锁           //锁时间           Long lock_timeout = currtTimeForRedis()+ LOCK_TIMEOUT +1;           if (redisTemplate.execute(new RedisCallback
() { @Override public Boolean doInRedis(RedisConnection redisConnection) throws DataAccessException { //定义序列化方式 RedisSerializer
serializer = redisTemplate.getStringSerializer(); byte[] value = serializer.serialize(lock_timeout.toString()); boolean flag = redisConnection.setNX(lockKey.getBytes(), value); return flag; } })){ //如果加锁成功 // LOG.info(threadName +"加锁成功 ++++ 111111"); //设置超时时间,释放内存 redisTemplate.expire(lockKey, LOCK_TIMEOUT, TimeUnit.MILLISECONDS); return lock_timeout; }else { //获取redis里面的时间 String result = redisTemplate.opsForValue().get(lockKey); Long currt_lock_timeout_str = result==null?null:Long.parseLong(result); //锁已经失效 if (currt_lock_timeout_str != null && currt_lock_timeout_str < System.currentTimeMillis()){ //判断是否为空,不为空时,说明已经失效,如果被其他线程设置了值,则第二个条件判断无法执行 //获取上一个锁到期时间,并设置现在的锁到期时间 Long old_lock_timeout_Str = Long.valueOf(redisTemplate.opsForValue().getAndSet(lockKey, lock_timeout.toString())); if (old_lock_timeout_Str != null && old_lock_timeout_Str.equals(currt_lock_timeout_str)){ //多线程运行时,多个线程签好都到了这里,但只有一个线程的设置值和当前值相同,它才有权利获取锁 // LOG.info(threadName + "加锁成功 ++++ 22222"); //设置超时间,释放内存 redisTemplate.expire(lockKey, LOCK_TIMEOUT, TimeUnit.MILLISECONDS); //返回加锁时间 return lock_timeout; } } } try { // LOG.info(threadName +"等待加锁, 睡眠100毫秒"); // TimeUnit.MILLISECONDS.sleep(100); TimeUnit.MILLISECONDS.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } } } /** * 解锁 * @param lockKey * @param lockValue * @param threadName */ @Override public synchronized void unlock(String lockKey, long lockValue, String threadName) { LOG.info(threadName + "执行解锁==========");//正常直接删除 如果异常关闭判断加锁会判断过期时间 //获取redis中设置的时间 String result = redisTemplate.opsForValue().get(lockKey); Long currt_lock_timeout_str = result ==null?null:Long.valueOf(result); //如果是加锁者,则删除锁, 如果不是,则等待自动过期,重新竞争加锁 if (currt_lock_timeout_str !=null && currt_lock_timeout_str == lockValue){ redisTemplate.delete(lockKey); LOG.info(threadName + "解锁成功------------------"); } } /** * 多服务器集群,使用下面的方法,代替System.currentTimeMillis(),获取redis时间,避免多服务的时间不一致问题!!! * @return */ @Override public long currtTimeForRedis(){ return redisTemplate.execute(new RedisCallback
() { @Override public Long doInRedis(RedisConnection redisConnection) throws DataAccessException { return redisConnection.time(); } }); } }
// 创建一个redis分布式锁 private static final String LOCK_NO = "redis_distribution_lock_no1";         RedisLockImpl redisLock = new RedisLockImpl(stringRedisTemplate);        // 加锁时间        Long lockTime;        String name = "uuid";        if ((lockTime = redisLock.lock((LOCK_NO) + "", name)) != null) {            // 业务逻辑            redisLock.unlock((LOCK_NO) + "", lockTime, name);        }

工具类。

转载于:https://www.cnblogs.com/chywx/p/9391602.html

你可能感兴趣的文章
Linux内核之数据双链表
查看>>
【云计算的1024种玩法】巧用迁云工具轻松实现服务器迁移到ECS
查看>>
MaxCompute,基于Serverless的高可用大数据服务
查看>>
Linux下MySQL表名区分大小写
查看>>
mysql主从配置
查看>>
《算法图解》之散列表
查看>>
golang for switch break 使用
查看>>
PHP自己实现var_dump函数
查看>>
A simple poem
查看>>
故事板控件无法和代码关联的问题解决
查看>>
锁分段技术、ConcurrentHashMap、扩容
查看>>
恭喜51CTO视频课程认证讲师、博主李海园喜得姐妹花
查看>>
我的友情链接
查看>>
DNS resource record的写法
查看>>
Flash知识点总结
查看>>
三层交换的测试1:级联的傻HUB
查看>>
手动添加linux用户
查看>>
Android Unable to execute dex: java.nio.BufferOverflowException
查看>>
Cocos2d-x3.2 EditBox的使用
查看>>
UTL_FILE学习
查看>>