Java深入學習28:Redisson分布式鎖的使用


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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM