當前位置:首頁 » 編程語言 » phpredis操作

phpredis操作

發布時間: 2024-05-06 22:56:24

A. php涓轟粈涔堜嬌鐢╮edis



1銆 Redis綆浠
redis鏄疦osql鏁版嵁搴撲腑浣跨敤杈冧負騫挎硾鐨勯潪鍏崇郴鍨嬪唴瀛樻暟鎹搴擄紝redis鍐呴儴鏄涓涓猭ey-value瀛樺偍緋葷粺銆傚畠鏀鎸佸瓨鍌ㄧ殑value綾誨瀷鐩稿規洿澶氾紝鍖呮嫭string(瀛楃︿覆)銆乴ist(閾捐〃)銆乻et(闆嗗悎)銆亃set(sorted set _鏈夊簭闆嗗悎)鍜宧ash錛堝搱甯岀被鍨嬶紝綾諱技浜嶫ava涓鐨刴ap錛夈俁edis鍩轟簬鍐呭瓨榪愯屽苟鏀鎸佹寔涔呭寲鐨凬oSQL鏁版嵁搴擄紝鏄褰撳墠鏈鐑闂ㄧ殑NoSql鏁版嵁搴撲箣涓錛屼篃琚浜轟滑縐頒負鏁版嵁緇撴瀯鏈嶅姟鍣ㄣ
2銆 浜掕仈緗戞椂浠h儗鏅涓嬪ぇ鏈洪亣錛屼粈涔堣佷嬌鐢∟osql錛
1錛 褰撴暟鎹閲忕殑鎬誨ぇ灝忎竴涓鏈哄櫒鏀句笉涓嬫椂銆
2錛 鏁版嵁緔㈠紩涓涓鏈哄櫒鐨勫唴瀛樻斁涓嶄笅鏃躲
3錛 璁塊棶閲忥紙璇誨啓娣峰悎錛変竴涓瀹炰緥鏀句笉涓嬫椂銆
鍗曟満鏃朵唬妯″瀷
濡傛灉姣忔″瓨鍌ㄦ垚鍗冧笂涓囨潯鏁版嵁錛岃繖鏍峰緢浼氬艱嚧MySQL鐨勬ц兘寰堝樊錛屽瓨鍌ㄤ互鍙婅誨彇閫熷害寰堟參錛岀劧鍚庡氨婕斿彉鎴愮紦瀛+mysql+鍨傜洿鎷嗗垎鐨勬柟寮忋
Cache浣滀負涓闂寸紦瀛
灝嗘墍鏈夌殑鏁版嵁鍏堜繚瀛樺埌緙撳瓨涓錛岀劧鍚庡啀瀛樺叆mysql涓錛屽噺灝忔暟鎹搴撳帇鍔涳紝鎻愰珮鏁堢巼銆 浣嗘槸褰撴暟鎹鍐嶆″炲姞鍒板張涓涓閲忕駭錛屼笂闈㈢殑鏂瑰紡涔熶笉鑳芥弧瓚抽渶奼傦紝鐢變簬鏁版嵁搴撶殑鍐欏叆鍘嬪姏澧炲姞錛孧emcached鍙鑳界紦瑙f暟鎹搴撶殑璇誨彇鍘嬪姏銆
璇誨啓闆嗕腑鍦ㄤ竴涓鏁版嵁搴撲笂璁╂暟鎹搴撲笉鍫閲嶈礋錛屽ぇ閮ㄥ垎緗戠珯寮濮嬩嬌鐢ㄤ富浠庡嶅埗鎶鏈鏉ヨ揪鍒拌誨啓鍒嗙伙紝浠ユ彁楂樿誨啓鎬ц兘鍜岃誨簱鐨勫彲鎵╁睍鎬с侻ysql鐨刴aster-slave妯″紡鎴愪負榪欎釜鏃跺欑殑緗戠珯鏍囬厤浜嗐
涓諱粠鍒嗙繪ā寮
鍦╮edis鐨勯珮閫熺紦瀛橈紝MySQL鐨勪富浠庡嶅埗錛岃誨啓鍒嗙葷殑鍩虹涔嬩笂錛岃繖鏃禡ySQL涓誨簱鐨勫啓鍘嬪姏寮濮嬪嚭鐜扮摱棰堬紝鑰屾暟鎹閲忕殑鎸佺畫鐚涘烇紝鐢變簬MyISAM浣跨敤琛ㄩ攣錛屽湪楂樺苟鍙戜笅浼氬嚭鐜頒弗閲嶇殑閿侀棶棰橈紝澶ч噺鐨勯珮騫跺彂MySQL搴旂敤寮濮嬩嬌鐢↖nnoDB寮曟搸浠f浛MyISAM銆
鍒嗚〃鍒嗗簱妯″紡
灝嗗彉鍖栧皬鐨勩佷笟鍔$浉鍏崇殑鏀懼湪涓涓鏁版嵁搴擄紝鍙樺寲澶氱殑錛屼笉鐩稿叧鐨勬暟鎹鏀懼湪涓涓鏁版嵁搴撱
3銆 nosql鏁版嵁搴撶殑浼樺娍
1錛夋槗鎵╁睍
榪欎簺綾誨瀷鐨勬暟鎹瀛樺偍涓嶉渶瑕佸滻瀹氱殑妯″紡錛屾棤闇澶氫綑鐨勬搷浣滃氨鍙浠ヨ繘琛屾í鍚戠殑鎵╁睍銆傜浉瀵逛簬鍏崇郴鍨嬫暟鎹搴撳彲浠ュ噺灝戣〃鍜屽瓧孌電壒鍒澶氱殑鎯呭喌銆備篃鏃犲瀷涔嬮棿鍦ㄦ灦鏋勭殑灞傞潰涓婂甫鏉ヤ簡鍙鎵╁睍鐨勮兘鍔
2錛夊ぇ鏁版嵁閲忔彁楂樻ц兘
3錛夊氭牱鐏墊椿鐨勬暟鎹妯″瀷
鍦╪osql涓涓嶄粎鍙浠ュ瓨鍌⊿tring錛宧ash錛宻et銆乑set絳夋暟鎹綾誨瀷錛岃繕鍙浠ヤ繚瀛榡avaBean浠ュ強澶氱嶅嶆潅鐨勬暟鎹綾誨瀷銆
4銆 NoSql鐨勫簲鐢
1錛 澶ф暟鎹鏃朵唬娣樺疂銆佸井淇°佷互鍙婂井鍗氱瓑閮藉箍娉涚殑浣跨敤浜唕edis鏁版嵁搴擄紝灝嗕竴浜涘滻瀹氫笉鍙樼殑鏁版嵁渚嬪傚︽牎錛屽尯鍩熺瓑鍥哄畾鐨勪俊鎮淇濆瓨鍦ㄥ叧緋誨瀷鏁版嵁搴撲腑銆傜劧鍚庡逛簬緇忓父鍙樺寲鐨勬暟鎹渚嬪傛窐瀹濇瘡涓鑺傛棩閮戒細鏈夋瘮杈冪儹闂ㄧ殑鎼滅儲鏄劇ず鍦ㄦ悳緔㈡嗭紝褰撹妭鏃ヨ繃鍘誨叧閿瀛楄嚜鍔ㄥ垹闄わ紝涓轟簡渚誇簬綆$悊錛屽彲浠ュ皢榪欎簺鏁版嵁淇濆瓨鍦╮edis鏁版嵁搴撲腑錛屽苟璁劇疆榪囨湡鏃墮棿錛屽埌杈炬椂闂村氨鑷鍔ㄥ垹闄ゃ
2錛変負浜嗙紦瑙f暟鎹搴撳帇鍔涳紝寰鍗氶栧厛灝嗗彂閫佺殑寰鍗氫繚瀛樺埌redis鏁版嵁搴擄紝鑷宸卞彲浠ョ珛鍗蟲煡鐪嬪埌錛岀劧鍚庡皢鍐呭瓨涓鐨勬暟鎹鍚屾ュ埌鍏崇郴鍨嬫暟鎹搴撱
浠ヤ笂鍐呭逛粎渚涘弬鑰冿紒
鎺ㄨ崘瑙嗛戞暀紼嬶細redis鏁欑▼

B. thinkphp5模型如何使用redis操作資料庫CURD操作

模型中添加如下代碼,可實現更新或插入前刪除緩存
protected static function init()
{
TurnGiftSetting::beforeInsert(function ($model) {
$redis = new Redis(config('redis'));
$redis->rm(self::$redisKey);
});
TurnGiftSetting::beforeUpdate(function ($model) {
$redis = new Redis(config('redis'));
$redis->rm(self::$redisKey);
});

TurnGiftSetting::beforeDelete(function ($model) {
$redis = new Redis(config('redis'));
$redis->rm(self::$redisKey);
});
TurnGiftSetting::beforeWrite(function ($model) {
$redis = new Redis(config('redis'));
$redis->rm(self::$redisKey);
});
}

C. thinkphp redis 怎麼選擇資料庫

1、redis 中的每一個資料庫,都由一個 redisDb 的結構存儲。其中,redisDb.id 存儲著 redis 資料庫以整數表示的號碼。redisDb.dict 存儲著該庫所有的鍵值對數據。redisDb.expires 保存著每一個鍵的過期時間。

2、當redis 伺服器初始化時,會預先分配 16 個資料庫(該數量可以通過配置文件配置),所有資料庫保存到結構 redisServer 的一個成員 redisServer.db 數組中。當我們選擇資料庫 select number 時,程序直接通過 redisServer.db[number] 來切換資料庫。有時候當程序需要知道自己是在哪個資料庫時,直接讀取 redisDb.id 即可。

3、既然我們知道一個資料庫的所有鍵值都存儲在redisDb.dict中,那麼我們要知道如果找到key的位置,就有必要了解一下dict 的結構了:

typedef struct dict {

// 特定於類型的處理函數
dictType *type;

// 類型處理函數的私有數據
void *privdata;

// 哈希表(2個)
dictht ht[2];

// 記錄 rehash 進度的標志,值為-1 表示 rehash 未進行
int rehashidx;

// 當前正在運作的安全迭代器數量
int iterators;
} dict;
由上述的結構可以看出,redis 的字典使用哈希表作為其底層實現。dict 類型使用的兩個指向哈希表的指針,其中 0 號哈希表(ht[0])主要用於存儲資料庫的所有鍵值,而1號哈希表主要用於程序對 0 號哈希表進行 rehash 時使用,rehash 一般是在添加新值時會觸發,這里不做過多的贅述。所以redis 中查找一個key,其實就是對進行該dict 結構中的 ht[0] 進行查找操作。

4、既然是哈希,那麼我們知道就會有哈希碰撞,那麼當多個鍵哈希之後為同一個值怎麼辦呢?redis採取鏈表的方式來存儲多個哈希碰撞的鍵。也就是說,當根據key的哈希值找到該列表後,如果列表的長度大於1,那麼我們需要遍歷該鏈表來找到我們所查找的key。當然,一般情況下鏈表長度都為是1,所以時間復雜度可看作o(1)。

二、當redis 拿到一個key 時,如果找到該key的位置。

了解了上述知識之後,我們就可以來分析redis如果在內存找到一個key了。

1、當拿到一個key後, redis 先判斷當前庫的0號哈希表是否為空,即:if (dict->ht[0].size == 0)。如果為true直接返回NULL。

2、判斷該0號哈希表是否需要rehash,因為如果在進行rehash,那麼兩個表中者有可能存儲該key。如果正在進行rehash,將調用一次_dictRehashStep方法,_dictRehashStep 用於對資料庫字典、以及哈希鍵的字典進行被動 rehash,這里不作贅述。

3、計算哈希表,根據當前字典與key進行哈希值的計算。

4、根據哈希值與當前字典計算哈希表的索引值。

5、根據索引值在哈希表中取出鏈表,遍歷該鏈表找到key的位置。一般情況,該鏈表長度為1。

6、當 ht[0] 查找完了之後,再進行了次rehash判斷,如果未在rehashing,則直接結束,否則對ht[1]重復345步驟。

到此我們就找到了key在內存中的位置了。

D. php 怎麼把session寫入redis

一、 安裝phpredis擴展
php連接redis需要安裝phpredis擴展。
下載地址:https://github.com/phpredis/phpredis/releases,選用相應版本。
筆者用的是php5.6.29,下載了phpredis-3.0.0安裝出了問題,於是換成phpredis-2.2.8,正常。
# tar zxvf phpredis-2.2.8.tar.gz && cd phpredis-2.2.8
# /usr/local/php/bin/phpize
# ./configure --with-php-config=/usr/local/php/bin/php-config
# make && make install
正常情況下會提示在下面目錄下生成redis.so文件
Installing shared extensions: /usr/local/php/lib/php/extensions/no-debug-non-zts-20131226/
# sed -i '$aextension="redis.so"' /usr/local/php/etc/php.ini
# service httpd restart
驗證:
# php -i | grep redis | grep -xq redis && echo ok || echo "phpredis extended failure"
二、 配置php連接redis(筆者使用的阿里雲redis)
# sed -i 's/session.save_handler.*/session.save_handler = redis/' /usr/local/php/etc/php.ini
# sed -i '/session.save_handler/asession.save_path ="tcp://xxxx.rds.aliyuncs.com?auth=redis密碼"' /usr/local/php/etc/php.ini
# service httpd restart

E. windows php使用redis怎麼後台運行

1. 進入 DOS窗口
2. 在進入Redis的安裝目錄
3. 輸入:redis-server --service-install redis.windows.conf --loglevel verbose ( 安裝redis服務 )
4. 輸入:redis-server --service-start ( 啟動服務 )
5. 輸入:redis-server --service-stop
主要是需要安裝redis的服務,電腦重新啟動之後如果redis的服務沒啟動需要手動啟動

F. phpredis igbinary的編譯安裝有關問題怎麼解決

1,下載安裝包
來到php的官方擴展庫下載地址,然後搜索redis,找到stable版本的穩定包,下載到本地,准備擴展安裝
pecl(The PHP Extension Community Library)地址:http://www.pecl.php.net/
redis下載地址:http://www.pecl.php.net/get/redis-2.2.4.tgz
2,編譯擴展包

首先解壓redis擴展包,然後進入到目錄中,執行:
/usr/local/php/bin/phpize
如果沒報錯,繼續執行:

./configure --with-php-config=/usr/local/php/bin/php-config
如果沒有報configure error 則繼續執行:
make && make install
成功之後會提示redis.so文件的存放目錄,如下:

然後將redis.so文件拷貝到php的擴展目錄下,然後修改php.ini文件增加一行:
extension=redis.so
重啟伺服器,就可以在phpinfo()中看到擴展信息了!

G. PHP Redis是使用connect還是pconnect

首先先介紹下connect和pconnect的區別。
connect:腳本結束之後連接就釋放了。

pconnect:腳本結束之後連接不釋放,連接保持在php-fpm進程中。
所以使用pconnect代替connect,可以減少頻繁建立redis連接的消耗。

H. thinkphp5.0鎬庝箞浣跨敤redis

璋冪敤鏂規硶
$redis = new Redis();
$redis->set('username','zongs');echo $redis->get('username');

I. php redis做mysql的緩存,怎麼非同步redis同步到mysql資料庫

對於變化頻率非常快的數據來說,如果還選擇傳統的靜態緩存方式(Memocached、File System等)展示數據,可能在緩存的存取上會有很大的開銷,並不能很好的滿足需要,而Redis這樣基於內存的NoSQL資料庫,就非常適合擔任實時數據的容器。

但是往往又有數據可靠性的需求,採用MySQL作為數據存儲,不會因為內存問題而引起數據丟失,同時也可以利用關系資料庫的特性實現很多功能。

所以就會很自然的想到是否可以採用MySQL作為數據存儲引擎,Redis則作為Cache。而這種需求目前還沒有看到有特別成熟的解決方案或工具,因此採用Gearman+PHP+MySQL UDF的組合非同步實現MySQL到Redis的數據復制。

MySQL到Redis數據復制方案

無論MySQL還是Redis,自身都帶有數據同步的機制,比較常用的MySQL的Master/Slave模式,就是由Slave端分析Master的binlog來實現的,這樣的數據復制其實還是一個非同步過程,只不過當伺服器都在同一內網時,非同步的延遲幾乎可以忽略。

那麼理論上也可以用同樣方式,分析MySQL的binlog文件並將數據插入Redis。但是這需要對binlog文件以及MySQL有非常深入的理解,同時由於binlog存在Statement/Row/Mixedlevel多種形式,分析binlog實現同步的工作量是非常大的。

因此這里選擇了一種開發成本更加低廉的方式,借用已經比較成熟的MySQL UDF,將MySQL數據首先放入Gearman中,然後通過一個自己編寫的PHP Gearman Worker,將數據同步到Redis。比分析binlog的方式增加了不少流程,但是實現成本更低,更容易操作。

Gearman的安裝與使用

Gearman是一個支持分布式的任務分發框架。設計簡潔,獲得了非常廣泛的支持。一個典型的Gearman應用包括以下這些部分:

Gearman Job Server:Gearman核心程序,需要編譯安裝並以守護進程形式運行在後台

Gearman Client:可以理解為任務的收件員,比如在後台執行一個發送郵件的任務,可以在程序中調用一個Gearman Client並傳入郵件的信息,然後就可以將執行結果立即展示給用戶,而任務本身會慢慢在後台運行。

Gearman Worker:任務的真正執行者,一般需要自己編寫具體邏輯並通過守護進程方式運行,Gearman Worker接收到Gearman Client傳遞的任務內容後,會按順序處理。

以前曾經介紹過類似的後台任務處理項目Resque。兩者的設計其實非常接近,簡單可以類比為:

Gearman Job Server:對應Resque的Redis部分

Gearman Client:對應Resque的Queue操作

Gearman Worker:對應Resque的Worker和Job

這里之所以選擇Gearman而不是Resque是因為Gearman提供了比較好用的MySQL UDF,工作量更小。

安裝Gearman及PHP Gearman擴展

以下均以Ubuntu12.04為例。

apt-get install gearman gearman-server libgearman-dev

檢查Gearman的運行狀況:

/etc/init.d/gearman-job-server status

* gearmand is running

說明Gearman已經安裝成功。

PHP的Gearman擴展可以通過pecl直接安裝

pecl install gearman

echo "extension=gearman.so">/etc/php5/conf.d/gearman.ini

service php5-fpm restart

但是實測發現ubuntu默認安裝的gearman版本過低,直接運行pecl install gearman會報錯

configure: error: libgearman version 1.1.0or later required

因此Gearman + PHP擴展建議通過編譯方式安裝,這里為了簡單說明,選擇安裝舊版本擴展:

pecl install gearman-1.0.3

Gearman + PHP實例

為了更容易理解後文Gearman的運行流程,這里不妨從一個最簡單的Gearman實例來說明,比如要進行一個文件處理的操作,首先編寫一個Gearman Client並命名為client.php:

<?php

$client =newGearmanClient();

$client->addServer();

$client->doBackground('writeLog','Log content');

echo '文件已經在後台操作';

運行這個文件,相當於模擬用戶請求一個Web頁面後,將處理結束的信息返回用戶:

php client.php

查看一下Gearman的狀況:

(echo status ; sleep 0.1)| netcat127.0.0.14730

可以看到輸出為

writeLog 100.

說明已經在Gearman中建立了一個名為writeLog的任務,並且有1個任務在隊列等待中。

而上面的4列分別代表當前的Gearman的運行狀態:

任務名稱

在等待隊列中的任務

正在運行的任務

正在運行的Worker進程

可以使用watch進行實時監控:

watch -n 1"(echo status; sleep 0.1) | nc 127.0.0.1 4730"

然後我們需要編寫一個Gearman Worker命名為worker.php:

<?php

$worker =newGearmanWorker();

$worker->addServer();

$worker->addFunction('writeLog','writeLog');while($worker->work());function writeLog($job){

$log = $job->workload();file_put_contents(__DIR__ .'/gearman.log', $log ." ", FILE_APPEND | LOCK_EX);}

Worker使用一個while死循環實現守護進程,運行

php worker.php

可以看到Gearman狀態變為:

writeLog 001

同時查看同目錄下gearman.log,內容應為從Client傳入的值Log content。

通過MySQL UDF + Trigger同步數據到Gearman

MySQL要實現與外部程序互通的最好方式還是通過MySQL UDF(MySQL user defined functions)來實現。為了讓MySQL能將數據傳入Gearman,這里使用了lib_mysqludf_json和gearman-mysql-udf的組合。

安裝lib_mysqludf_json

使用lib_mysqludf_json的原因是因為Gearman只接受字元串作為入口參數,可以通過lib_mysqludf_json將MySQL中的數據編碼為JSON字元串

apt-get install libmysqlclient-dev

wget https://github.com/mysqludf/lib_mysqludf_json/archive/master.zip

unzip master.zip

cd lib_mysqludf_json-master/

rm lib_mysqludf_json.so

gcc $(mysql_config --cflags)-shared -fPIC -o lib_mysqludf_json.so lib_mysqludf_json.c

可以看到重新編譯生成了 lib_mysqludf_json.so 文件,此時需要查看MySQL的插件安裝路徑:

mysql -u root -pPASSWORD --execute="show variables like '%plugin%';"+---------------+------------------------+|Variable_name|Value|+---------------+------------------------+| plugin_dir |/usr/lib/mysql/plugin/|+---------------+------------------------+

然後將 lib_mysqludf_json.so 文件復制到對應位置:

cp lib_mysqludf_json.so /usr/lib/mysql/plugin/

最後登入MySQL運行語句注冊UDF函數:

CREATE FUNCTION json_object RETURNS STRING SONAME 'lib_mysqludf_json.so';

安裝gearman-mysql-udf

方法幾乎一樣:

apt-get install libgearman-dev

wget https://launchpad.net/gearman-mysql-udf/trunk/0.6/+download/gearman-mysql-udf-0.6.tar.gz

tar -xzf gearman-mysql-udf-0.6.tar.gz

cd gearman-mysql-udf-0.6./configure --with-mysql=/usr/bin/mysql_config

-libdir=/usr/lib/mysql/plugin/

make && make install

登入MySQL運行語句注冊UDF函數:

CREATE FUNCTION gman_do_background RETURNS STRING SONAME 'libgearman_mysql_udf.so';

CREATE FUNCTION gman_servers_set RETURNS STRING SONAME 'libgearman_mysql_udf.so';

最後指定Gearman伺服器的信息:

SELECT gman_servers_set('127.0.0.1:4730');

通過MySQL觸發器實現數據同步

最終同步哪些數據,同步的條件,還是需要根據實際情況決定,比如將數據表data的數據在每次更新時同步,那麼編寫Trigger如下:

DELIMITER $$

CREATE TRIGGER datatoredis AFTER UPDATE ON data

FOR EACH ROW BEGIN

SET @ret=gman_do_background('syncToRedis', json_object(NEW.id as`id`, NEW.volume as`volume`));END$$

DELIMITER ;

嘗試在資料庫中更新一條數據查看Gearman是否生效。

Gearman PHP Worker將MySQL數據非同步復制到Redis

Redis作為時下當熱的NoSQL緩存解決方案無需過多介紹,其安裝及使用也非常簡單:

apt-get install redis-server

pecl install redis

echo "extension=redis.so">/etc/php5/conf.d/redis.ini

然後編寫一個Gearman Worker:redis_worker.php

#!/usr/bin/env php<?

$worker =newGearmanWorker();

$worker->addServer();

$worker->addFunction('syncToRedis','syncToRedis');

$redis =newRedis();

$redis->connect('127.0.0.1',6379);while($worker->work());function syncToRedis($job){global $redis;

$workString = $job->workload();

$work = json_decode($workString);if(!isset($work->id)){returnfalse;}

$redis->set($work->id, $workString);}

最後需要將Worker在後台運行:

nohup php redis_worker.php &

通過這種方式將MySQL數據復制到Redis,經測試單Worker基本可以瞬時完成。

J. php 使用redis鎖限制並發訪問類示例

本文介紹了php
使用redis鎖限制並發訪問類,並詳細的介紹了並發訪問限制方法。
1.並發訪問限制問題
對於一些需要限制同一個用戶並發訪問的場景,如果用戶並發請求多次,而伺服器處理沒有加鎖限制,用戶則可以多次請求成功。
例如換領優惠券,如果用戶同一時間並發提交換領碼,在沒有加鎖限制的情況下,用戶則可以使用同一個換領碼同時兌換到多張優惠券。
偽代碼如下:
if
A(可以換領)

B(執行換領)

C(更新為已換領)
D(結束)
如果用戶並發提交換領碼,都能通過可以換領(A)的判斷,因為必須有一個執行換領(B)後,才會更新為已換領(C)。因此如果用戶在有一個更新為已換領之前,有多少次請求,這些請求都可以執行成功。
2.並發訪問限制方法
使用文件鎖可以實現並發訪問限制,但對於分布式架構的環境,使用文件鎖不能保證多台伺服器的並發訪問限制。
Redis是一個開源的使用ANSI
C語言編寫、支持網路、可基於內存亦可持久化的日誌型、Key-Value資料庫,並提供多種語言的API。
本文將使用其setnx方法實現分布式鎖功能。setnx即Set
it
N**ot
eX**ists。
當鍵值不存在時,插入成功(獲取鎖成功),如果鍵值已經存在,則插入失敗(獲取鎖失敗)
RedisLock.class.PHP
<?php
/**
*
Redis鎖操作類
*
Date:
2016-06-30
*
Author:
fdipzone
*
Ver:
1.0
*
*
Func:
*
public
lock
獲取鎖
*
public
unlock
釋放鎖
*
private
connect
連接
*/
class
RedisLock
{
//
class
start
private
$_config;
private
$_redis;
/**
*
初始化
*
@param
Array
$config
redis連接設定
*/
public
function
__construct($config=array()){
$this->_config
=
$config;
$this->_redis
=
$this->connect();
}
/**
*
獲取鎖
*
@param
String
$key
鎖標識
*
@param
Int
$expire
鎖過期時間
*
@return
Boolean
*/
public
function
lock($key,
$expire=5){
$is_lock
=
$this->_redis->setnx($key,
time()+$expire);
//
不能獲取鎖
if(!$is_lock){
//
判斷鎖是否過期
$lock_time
=
$this->_redis->get($key);
//
鎖已過期,刪除鎖,重新獲取
if(time()>$lock_time){
$this->unlock($key);
$is_lock
=
$this->_redis->setnx($key,
time()+$expire);
}
}
return
$is_lock?
true
:
false;
}
/**
*
釋放鎖
*
@param
String
$key
鎖標識
*
@return
Boolean
*/
public
function
unlock($key){
return
$this->_redis->del($key);
}
/**
*
創建redis連接
*
@return
Link
*/
private
function
connect(){
try{
$redis
=
new
Redis();
$redis->connect($this->_config['host'],$this->_config['port'],$this->_config['timeout'],$this->_config['reserved'],$this->_config['retry_interval']);
if(empty($this->_config['auth'])){
$redis->auth($this->_config['auth']);
}
$redis->select($this->_config['index']);
}catch(RedisException
$e){
throw
new
Exception($e->getMessage());
return
false;
}
return
$redis;
}
}
//
class
end
?>
demo.php
<?php
require
'RedisLock.class.php';
$config
=
array(
'host'
=>
'localhost',
'port'
=>
6379,
'index'
=>
0,
'auth'
=>
'',
'timeout'
=>
1,
'reserved'
=>
NULL,
'retry_interval'
=>
100,
);
//
創建redislock對象
$oRedisLock
=
new
RedisLock($config);
//
定義鎖標識
$key
=
'mylock';
//
獲取鎖
$is_lock
=
$oRedisLock->lock($key,
10);
if($is_lock){
echo
'get
lock
success<br>';
echo
'do
sth..<br>';
sleep(5);
echo
'success<br>';
$oRedisLock->unlock($key);
//
獲取鎖失敗
}else{
echo
'request
too
frequently<br>';
}
?>
測試方法:
打開兩個不同的瀏覽器,同時在A,B中訪問demo.php
如果先訪問的會獲取到鎖
輸出
get
lock
success
do
sth..
success
另一個獲取鎖失敗則會輸出request
too
frequently
保證同一時間只有一個訪問有效,有效限制並發訪問。
為了避免系統突然出錯導致死鎖,所以在獲取鎖的時候增加一個過期時間,如果已超過過期時間,即使是鎖定狀態都會釋放鎖,避免死鎖導致的問題。
源碼下載地址:點擊查看

熱點內容
百度雲7z解壓 發布:2024-11-27 22:41:36 瀏覽:711
哈利波特不同伺服器有什麼不同 發布:2024-11-27 22:33:45 瀏覽:77
鎖ip伺服器 發布:2024-11-27 22:31:48 瀏覽:176
腳本刷精粹 發布:2024-11-27 22:30:31 瀏覽:991
電腦定時清理文件的腳本 發布:2024-11-27 22:27:49 瀏覽:996
安卓系統傳奇哪個好玩 發布:2024-11-27 22:26:17 瀏覽:253
oracle存儲過程重命名 發布:2024-11-27 22:12:51 瀏覽:547
串口伺服器幾個ip 發布:2024-11-27 21:58:21 瀏覽:325
麥芒5腳本 發布:2024-11-27 21:45:33 瀏覽:848
dnf龍貓腳本 發布:2024-11-27 21:45:15 瀏覽:959