相關(guān)關(guān)鍵詞
關(guān)于我們
最新文章
Redis構(gòu)建分布式鎖

1、前言
為什么要構(gòu)建鎖呢?因為構(gòu)建合適的鎖可以在高并發(fā)下能夠保持數(shù)據(jù)的一致性,即客戶端在執(zhí)行連貫的命令時上鎖的數(shù)據(jù)不會被別的客戶端的更改而發(fā)生錯誤。同時還能夠保證命令執(zhí)行的成功率。
看到這里你不禁要問redis中不是有事務(wù)操作么?事務(wù)操作不能夠?qū)崿F(xiàn)上面的功能么?
的確,redis中的事務(wù)可以watch可以監(jiān)控數(shù)據(jù),從而能夠保證連貫執(zhí)行的時數(shù)據(jù)的一致性,但是我們必須清楚的認識到,在多個客戶端同時處理相同的數(shù)據(jù)的時候,很容易導致事務(wù)的執(zhí)行失敗,甚至會導致數(shù)據(jù)的出錯。
在關(guān)系型數(shù)據(jù)庫中,用戶首先向數(shù)據(jù)庫服務(wù)器發(fā)送BEGIN,然后執(zhí)行各個相互一致的寫操作和讀操作,最后用戶可以選擇發(fā)送COMMIT來確認之前的修改,或者發(fā)送ROLLBACK進行回滾。
在redis中,通過特殊的命令MULTI為開始,之后用戶傳入一連貫的命令,最后EXEC為結(jié)束(在這一過程中可以使用watch進行監(jiān)控一些key)。進一步分析,redis事務(wù)中的命令會先推入隊列,等到EXEC命令出現(xiàn)的時候才會將一條條命令執(zhí)行。假若watch監(jiān)控的key發(fā)生改變,這個事務(wù)將會失敗。這也就說明Redis事務(wù)中不存在鎖,其他客戶端可以修改正在執(zhí)行事務(wù)中的有關(guān)數(shù)據(jù),這也就為什么在多個客戶端同時處理相同的數(shù)據(jù)時事務(wù)往往會發(fā)生錯誤。
2、簡單理解redis的單線程IO多路復用
Redis采用單線程IO多路復用模型來實現(xiàn)高內(nèi)存數(shù)據(jù)服務(wù)。何為單線程IO多路復用呢?從字面的意思可以知道redis采用的是單線程、使用的是多個IO。整個過程簡單的來講就是,哪個命令的數(shù)據(jù)流先到達就先執(zhí)行。
請看下面的形象理解圖:圖中是一座窄橋,只能允許一輛車通過,左邊是車輛進入的通道,哪一輛車先到達就先進入。即哪個IO流先到達就先處理哪個。
Linux下網(wǎng)絡(luò)IO使用socket套接字來通訊,普通IO模型只能監(jiān)聽一個socket,而IO多路復用可同時監(jiān)控多個socket。IO多路復用避免阻塞在IO上,單線程保存多個socket的狀態(tài)后輪循處理。
3、并發(fā)測試
我們就模擬一個簡單典型的并發(fā)測試,然后從這個測試中得出問題,再進一步研究。
并發(fā)測試思路:
1、在redis中設(shè)置一個字符串count,運用程序?qū)⑵淙〕鰜砑?1,再存儲回去,一直循環(huán)十萬次
2、在兩個瀏覽器上同時執(zhí)行這個代碼
3、將count取出來,查看結(jié)果
測試步驟:
1、建立test.php文件
<?php $redis=new Redis(); $redis->connect('192.168.95.11','6379'); for ($i=0; $i < 100000; $i++) { $count=$redis->get('count'); $count=$count+1; $redis->set('count',$count); } echo "this OK"; ?>