Java深入学习28:Redisson分布式锁的使用
情况1-常规情况,没有任何同步锁,使用Jmeter模拟多线程
问题:结果发现numTest会出现重复读写的情况(numTest = 6)
@RestController public classRedissonController { static int numTest = 0; @GetMapping("/test") publicString test(){ System.out.println("num: " + ++numTest); return "success"+ Math.random()*100; } } numTest: 2numTest: 3numTest: 1numTest: 4numTest: 5 numTest: 6numTest: 7 numTest: 6numTest: 8numTest: 9numTest: 10
情况2- 我们使用Lock锁
解决的问题:单服务的情况下,解决了数据重复读写的问题
新的问题:很明显,如果是分布式服务,Lock锁是内存锁(synchronized也是),还是会出现重复读物数据的情况
@RestController public classRedissonController { static int numLock = 0; @GetMapping("/lock") publicString lock(){ Lock lock = newReentrantLock(); lock.lock(); try{ System.out.println("numLock: " + ++numLock); } finally{ lock.unlock(); } return "success"+ Math.random()*100; } } numLock: 1numLock: 2numLock: 3numLock: 4numLock: 5numLock: 6numLock: 7numLock: 9numLock: 10numLock: 11numLock: 12numLock: 8
情况3-使用redisson分布式锁解决分布式下高并发下,数据重复读取
模拟的先决条件
1- 使用Redis保存公有数据(数据库也行);
2-使用Ngnix负载均衡搭建分布式服务(见附录)
3-使用Jmeter模拟并发请求(见附录)
3-1-当没有使用redisson锁时,结果如下,数据大量的重复读取
@RestController public classRedissonController { @Autowired privateRedisTemplate redisTemplate;
//直接从redis读写数据 @GetMapping("/redisson") publicString 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 classRedissonController { @Autowired privateRedissonClient client; @Autowired privateRedisTemplate redisTemplate; //使用redisson分布式锁从redis读写数据 @GetMapping("/redisson/lock") publicString 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