一、前言
前一篇 Redis应用之一自增编号 我们主要介绍了使用INCR命令来生成不重复的编号,今天我们来了解Redis另外一个命令SET NX的用途,对于单体应用我们可以简单使用像synchronized这样的关键字来给代码块加锁,但对于分布式应用要实现锁机制就必须依赖于中间件,现在一般分布式锁主要依赖于Redis、Zookeeper或Google的Chubby来实现, 今天我们看一下如何用Redis的SETNX命令来实现分布式锁。
分布式锁定义:在分布式环境下,一个方法在同一时间只能被一台机器中的一个线程执行。
说明:我的文章目的是用最简单的语言和代码来说清楚一件事情,严谨性肯定是不够的,希望读者能注意辨析。
二、SETNX命令说明
SET key value NX PX
NX:表示key不存在时设置,如果key存在则返回NULL
PX:设置过期时间,单位毫秒
上面的set nx 返回OK表示拿到锁,如果返回nil表示拿锁失败,资源被其它线程占用。
三、模拟分布式环境并发扣减库存
在https://start.spring.io/快速创建Springboot工程框架,引入web和data-redis依赖。
1、使用Redis存储库存值
set inventory:9321785256118 1000
2、在代码中获取当前库存数然后进行扣减,最后又设置到Redis中去。
3、模拟请求
将代码部署到两台机器,然后用Jmeter创建两个线程组,分别对两台机器接口进行请求,每个请求只使用一个线程请求500次,执行结果 Redis中的库存值并不为0,而是大于0不确定的值(第一次结果348,第二次结果55),如果改成每个线程组的线程数为10个请求次数为50次,这时结果会更大一些。
这就是分布式环境多台机器并发的问题,多台机器从Redis中取出相同的值,然后分别再执行扣减库存操作,结果就会发生超卖的问题,线程数更多结果更大这是因为更多的请求从Redis中取出了相同的值,然后进行扣减库存
四、在代码中加入Redis分布式锁
然后同样用Jmeter发向两台机器发请求,当每台机器1个并发,库存数最后为0,当提高到每台机器10个并发,库存数为75,这段代码还是有一些问题的,我们下一次再讲如何优化以及如何使用Redisson解决分布式并发问题。