基于redis实现分布式锁

it2023-06-06  77

今天看博客看到了一条关于实现分布式锁的标题,正好有空闲时间,便自己动手简单实现基于redis的分布式锁;

大体实现思路:

1.在redis中设置一个(key,value),并赋予其过期时间,防止死锁,将这个(key,value)当做一个锁,并将value返回,当释放锁的时候进行判断。 2.获取锁的时候同样设置一个过期时间,如果超时,则停止获取锁。 3.释放锁的时候,先对比判断标识,如果符合条件,则删除key,达到释放锁的目的。

具体代码:

package com.chat.api.test.redisLock; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import redis.clients.jedis.Transaction; import java.util.List; import java.util.UUID; public class RedisLock { private JedisPool jedisPool; public RedisLock(JedisPool jedisPool){ this.jedisPool = jedisPool; } /** * 添加锁 * @param lock * @param requestTimeout * @param timeout * @return */ public String addLock(String lock,Long requestTimeout,Long timeout){ Jedis jedis = null; String identify = null; try { jedis = jedisPool.getResource(); //生成一个随机val String val = UUID.randomUUID().toString(); String key = lock; //锁的超时时间 int expire = (int) (timeout/1000); //获取锁的超时时间,超过时长则停止获取 long end = System.currentTimeMillis() + requestTimeout; while (System.currentTimeMillis() < end){ if (jedis.setnx(key,val) == 1){ jedis.expire(key,expire); //返回val,释放锁时进行确认 identify = val; return identify; }; //如果这里返回-1,则代表key没有过期时间,这里对key添加一个过期时间 if (jedis.ttl(key) == -1){ jedis.expire(key,expire); } try { Thread.sleep(10); }catch (Exception e){ Thread.currentThread().interrupt(); } } }catch (Exception e){ e.printStackTrace(); }finally { if (jedis != null){ jedis.close(); } } return identify; } /** * 释放锁 * @param lock * @param identify * @return */ public boolean releaseLock(String lock,String identify){ Jedis jedis = null; String key = lock; boolean flag = false; try { jedis = jedisPool.getResource(); while (true){ //开始事务之前先监视key jedis.watch(key); //释放锁之前先判断是否是该锁 if (identify.equals(jedis.get(key))){ //开始事务 Transaction transaction = jedis.multi(); transaction.del(key); //提交事务 List<Object> exec = transaction.exec(); if (exec == null){ continue; } flag = true; jedis.unwatch(); break; } } }catch (Exception e){ e.printStackTrace(); }finally { if (jedis != null){ jedis.close(); } } return flag; } } package com.chat.api.test.redisLock; import redis.clients.jedis.JedisPool; import redis.clients.jedis.JedisPoolConfig; public class TestService { private static JedisPool pool = null ; private RedisLock redisLock = new RedisLock(pool); int n = 100; static { JedisPoolConfig config = new JedisPoolConfig(); config.setMaxTotal(200); config.setMaxIdle(10); config.setMaxWaitMillis(100*1000); config.setTestOnBorrow(true); pool = new JedisPool(config,"127.0.0.1",6379,3000,"123456"); } public void seckill(){ // 返回锁的value值,供释放锁时候进行判断 String identifier = redisLock.addLock("resource", 5000L, 1000L); System.out.println(Thread.currentThread().getName() + "获得了锁"); System.out.println(--n); redisLock.releaseLock("resource", identifier); } }

下面是测试代码:

package com.chat.api.test.redisLock; public class ThreadTest extends Thread { private TestService service; public ThreadTest(TestService service){ this.service = service; } @Override public void run() { service.seckill(); } } package com.chat.api.test.redisLock; public class test { public static void main(String[] args) { TestService service = new TestService(); for (int i = 0; i < 50; i++) { ThreadTest threadA = new ThreadTest(service); threadA.start(); } } }

执行结果:

最新回复(0)