Redis:分布式锁Watch

Redis:分布式锁Watch


关键词

  • watch乐观锁(判断是否发生变化)
  • 秒杀简单实现

一、利用Watch实现Redis乐观锁

乐观锁基于CAS(Compare And Swap)思想(比较并替换),是不具有互斥性(乐观),不会产生锁等待而消耗资源,但是需要反复的重试,但也是因为重试的机制,能比较快的响应。因此我们可以利用redis来实现乐观锁。具体思路如下:

1、利用redis的watch功能,监控这个redisKey的状态值
2、获取redisKey的值
3、创建redis事务
4、给这个key的值+1
5、然后去执行这个事务,如果key的值被修改过则回滚,key不加1 (有成功的,有不成功的)

Redis:分布式锁Watch_第1张图片
Redis 参考了多线程中使用的 CAS(比较与交换,Compare And Swap)去执行的。在数据高并发环境的操作中,把这样的一个机制称为乐观锁。

  • 乐观锁:不互斥,不需要等待,需要返回重试
  • 悲观锁:具有互斥性,需要等待,效率低

二、Redis乐观锁实现秒杀(比较弱的秒杀)

public class Second {
	public static void main(String[] arg) {
		String redisKey = "lock";
		ExecutorService executorService = Executors.newFixedThreadPool(20);
		try {
			Jedis jedis = new Jedis("127.0.0.1", 6378);
			// 初始值
			jedis.set(redisKey, "0");
			jedis.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		for (int i = 0; i < 1000; i++) {
			executorService.execute(() -> {
				Jedis jedis1 = new Jedis("127.0.0.1", 6378);
					try {
						jedis1.watch(redisKey);
						String redisValue = jedis1.get(redisKey);
						int valInteger = Integer.valueOf(redisValue);
						String userInfo = UUID.randomUUID().toString();
						// 没有秒完
						if (valInteger < 20) {
							Transaction tx = jedis1.multi();
							tx.incr(redisKey);
							List list = tx.exec();
								// 秒成功  失败返回空list而不是空
								if (list != null && list.size() > 0) {
								System.out.println("用户:" + userInfo + ",秒杀成功!
								当前成功人数:" + (valInteger + 1));
								}
								// 版本变化,被别人抢了。
								else {
								System.out.println("用户:" + userInfo + ",秒杀失
								败");
								}
						}
						// 秒完了
						else {
							System.out.println("已经有20人秒杀成功,秒杀结束");
						}
						} catch (Exception e) {
							e.printStackTrace();
						} finally {
							jedis1.close();
						}
						});
				}
					executorService.shutdown();
				}
}

Redis:分布式锁Watch_第2张图片

你可能感兴趣的:(面试真题,大型分布式系统缓存架构,Redis分布式锁Watch,乐观锁CAS)