Java深入学习28:Redisson分布式锁的使用
情况1- 常规情况,没有任何同步锁,使用Jmeter模拟多线程
问题:结果发现numTest会出现重复读写的情况(numTest = 6)
@RestController public class RedissonController { static int numTest = 0; @GetMapping("/test") public String test(){ System.out.println("num: " + ++numTest); return "success"+ Math.random()*100; } } numTest: 2 numTest: 3 numTest: 1 numTest: 4 numTest: 5 numTest: 6 numTest: 7 numTest: 6 numTest: 8 numTest: 9 numTest: 10
情况2- 我们使用Lock锁
解决的问题:单服务的情况下,解决了数据重复读写的问题
新的问题:很明显,如果是分布式服务,Lock锁是内存锁(synchronized也是),还是会出现重复读物数据的情况
@RestController public class RedissonController { static int numLock = 0; @GetMapping("/lock") public String lock(){ Lock lock = new ReentrantLock(); lock.lock(); try { System.out.println("numLock: " + ++numLock); } finally { lock.unlock(); } return "success"+ Math.random()*100; } } numLock: 1 numLock: 2 numLock: 3 numLock: 4 numLock: 5 numLock: 6 numLock: 7 numLock: 9 numLock: 10 numLock: 11 numLock: 12 numLock: 8
情况3- 使用redisson分布式锁解决分布式下高并发下,数据重复读取
模拟的先决条件
1- 使用Redis保存公有数据(数据库也行);
2- 使用Ngnix负载均衡搭建分布式服务(见附录)
3- 使用Jmeter模拟并发请求(见附录)
3-1- 当没有使用redisson锁时,结果如下,数据大量的重复读取
@RestController public class RedissonController { @Autowired private RedisTemplate redisTemplate;
//直接从redis读写数据 @GetMapping("/redisson") public String redisson(){ int num = (int)redisTemplate.opsForValue().get(key); System.out.println("numRedisson: " + ++num); redisTemplate.opsForValue().set(key,num); return "success"+ Math.random()*100; } }
3-2- 当使用redisson锁时,结果如下,分布式下两台服务器,数据读写正常不会重复
@RestController public class RedissonController { @Autowired private RedissonClient client; @Autowired private RedisTemplate redisTemplate; //使用redisson分布式锁从redis读写数据 @GetMapping("/redisson/lock") public String redissonLockTest(){ RLock testLock = client.getLock("testLock"); testLock.lock(); try { if(redisTemplate.hasKey(key)){ int num = (int)redisTemplate.opsForValue().get(key); System.out.println("numRedissonLock: " + ++num); redisTemplate.opsForValue().set(key,num); } }finally { testLock.unlock(); } return "success"+ Math.random()*100; } }
附录 -使用Ngnix负载均衡搭建分布式服务
1-下载并安装Nginx,参考博客,只要下载安装包,正常启动就好。
启动Ngnix指令:在安装目录下:nginx.exe
关闭Ngnix指令:在安装目录下:taskkill /f /t /im nginx.exe
2- Ngnix负载均衡配置
upstream upstream_name{ server 127.0.0.1:8001 weight=1;#第一台服务器 server 127.0.0.1:8002 weight=1;#第二台服务器 } server { listen 80; server_name localhost; location / { #这个至关重要,表示代理的时候设置主机名(IP)和端口,不设置会无法转发请求,这里其实就是代理Nginx本机IP以及监听端口 proxy_set_header Host $host:8080; #这个是获取到请求客户端的真实IP而不是Nginx代理机器的IP proxy_set_header X-Real-IP $remote_addr; #这个是转发 proxy_set_header X-Forwarded-For $Proxy_add_x_forwarded_for; #这个名字可以随便取,只要能匹配到upstream的名字即可 proxy_pass http://upstream_name; } }
附录-使用Jmeter模拟并发请求
1-Jmeter的使用参考博客
2-模拟部分截图
END