Py学习  »  问与答

使用redis实现分布式锁方法步骤详解

w8494444 • 7 年前 • 1271 次点击  

大家都知道Redis数据库是NoSQL的一种,目前在互联网公司中在作为缓存广泛的使用者,其实利用Redis的setnx还可以快速实现一个分布式锁,公司的业务就需要使用分布式锁保证数据的唯一性,经检索在网上发现已经有活雷锋分享了一套,本着不在重新发明轮子的想法,测试了一下好像没有问题,几乎不用对原代码进行修改,就能使用,下面就分享在这里,供需要的朋友参考。原文里面还有对实现的原理进行解释,所以本文就不再赘述,详情请通过参考资料进行访问。   package cn.bridgeli.distributedlock;   import java.util.UUID;import java.util.concurrent.CountDownLatch;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.atomic.AtomicInteger;   import org.slf4j.Logger;import org.slf4j.LoggerFactory;   import redis.clients.jedis.Jedis;import redis.clients.jedis.JedisPool;import redis.clients.jedis.JedisPoolConfig;import redis.clients.jedis.Transaction;   public class RedisDistributedLock {   private static final Logger LOG = LoggerFactory.getLogger(RedisDistributedLock.class);   private static final String redisHost = "127.0.0.1";   private static final int port = 6381;   private static JedisPoolConfig config;   private static JedisPool pool;   private static ExecutorService service;   private static int ThLeng = 10;   private static CountDownLatch latch;   private static AtomicInteger Countor = new AtomicInteger(0);   private static int count = 0;   private static String LockName = "mylock_test10";   static {   // 利用Redis连接池,保证多个线程利用多个连接,充分模拟并发性   config = new JedisPoolConfig();   config.setMaxIdle(10);   config.setMaxWaitMillis(1000);   config.setMaxTotal(30);   pool = new JedisPool(config, redisHost, port);   // 利用ExecutorService 管理线程   service = Executors.newFixedThreadPool(ThLeng);   // CountDownLatch保证主线程在全部线程结束之后退出   latch = new CountDownLatch(ThLeng);   }   /    获取锁 tips:生成一个UUID,作为Key的标识,不断轮询lockName,直到set成功,表示成功获取锁。    其他的线程在set此lockName时被阻塞直到超时。       @param pool    @param lockName    @param timeouts    @return 锁标志   /   public static String getLock(JedisPool pool, String lockName, long timeouts) {   Jedis client = pool.getResource();   try {   String value = UUID.randomUUID().toString();   long timeWait = System.currentTimeMillis() + timeouts * 1000;   while (System.currentTimeMillis() < timeWait) {   if (client.setnx(lockName, value) == 1) {   LOG.info("lock geted");   return value;   }   try {   Thread.sleep(1000);   } catch (InterruptedException e) {   e.printStackTrace();   }   }   LOG.info("get lock timeouts");   } finally {   // pool.returnBrokenResource(client);   pool.returnResource(client);   }   return null;   }   /    释放锁 tips:对lockName做watch,开启一个事务,删除以LockName为key的锁,删除后,此锁对于其他线程为可争抢的。       @param pool    @param lockName    @param value   /   public static void relaseLock(JedisPool pool, String lockName, String value) {   Jedis client = pool.getResource();   try {   while (true) {   client.watch(lockName);   if (client.get(lockName).equals(value)) {   Transaction tx = client.multi();   tx.del(lockName);   tx.exec();   return;   }   client.unwatch();   }   } finally {   // pool.returnBrokenResource(client);   pool.returnResource(client);   }   }   public static void main(String args[]) {   for (int i = 0; i < ThLeng; i++) {   String tName = "thread-" + i;   Thread t = new Thread(new SubAddThread(pool, tName));   LOG.info(tName + "inited...");   service.submit(t);   }   service.shutdown();   try {   latch.await();   } catch (InterruptedException e) {   e.printStackTrace();   }   LOG.info(Countor.get() + "");   LOG.info(count + "");   }   public static class SubAddThread implements Runnable {   private String name;   private JedisPool pool;   public SubAddThread(JedisPool pool, String uname) {   this.pool = pool;   this.name = uname;   }   @Override   public void run() {   for (int i = 0; i < 100; i++) {   LOG.info(name + " starting...");   String valuse = getLock(pool, LockName, 50);   LOG.info(name + " get Lock " + valuse);   count++;   relaseLock(pool, LockName, valuse);   Countor.incrementAndGet();   LOG.info(name + " " + count);   }   latch.countDown();   LOG.info(name + " complated");   }   }   }

来源:BridgeLi's Blog

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/1767
 
1271 次点击