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
