redis的併發問題處理

2021-08-21 08:07:12 字數 2214 閱讀 6733

簡單模擬下redis併發的場景:

建立2個檔案1.php,2.php,內容如下:

<?php

$redis=new redis();

$redis->connect('127.0.0.1');

$price=$redis->get('price');

sleep(10);

$price=$price+10;

$redis->set('price',$price);

price的初始值為10,分別執行這2個檔案,發現最後price的值是20,而不是我們預想中的值30.這就是redis併發問題的乙個簡單的場景,那麼要如何應對呢 ?有以下幾種方法可以解決,用什麼方法取決於業務需求。

1.使用redis的事務處理

<?php

$redis=new redis();

$redis->connect('127.0.0.1');

function doll()

$redis->watch('price');//監聽 當監聽的值發生變化的話就執行失敗

$redis->get('price');

//模擬併發 模擬當其他執行緒也同時在對price進行寫操作 此時事務將執行失敗 放在事務開始之前

doll();

$redis->multi();//事務開始標誌

$redis->set('price',20);

// sleep(5);

$res=$redis->exec();//執行事務

var_dump($res);exit;

假設price的初始值為0,那麼執行完該指令碼後,price的值為10,$res的值為false,也就避免了併發操作price的問題。也就是說,當你監聽了price之後,如果price的值發生了變化(其他併發操作),那麼事務將失敗。但是這個場景有個缺點就是,假如某個時刻同時有100個使用者進行寫操作,由於他們watch的price是同乙個值,那麼只要有乙個人寫入成功之後,由於price的值已經發生了變化,所以其他99個使用者的操作都將失敗。

2.加個自定義鎖(排它鎖),當有使用者在對price進行寫操作的時候,其他使用者不能讀寫。

<?php 

/*** 實現redis分布鎖

*/$redis=new redis();

$redis->connect('127.0.0.1');

$key        = 'price';       //要更新資訊的快取key

$lockname    = 'lock'.$key; //設定鎖key

$lockexpire = 10;           //設定鎖的有效期為5秒

//建立鎖

$lock=$redis->setnx($lockname,time()+$lockexpire);

//如果鎖不存在($lock為true) 說明鎖建立成功 也就是說現在沒人正在對price進行寫操作 可以對price進行寫操作

//如果鎖存在 但是已經過期 也可以進行對price進行寫操作 並重新設定過期時間

if ($lock ||  ($redis->get($lockname)getset($lockname,time()+$lockexpire)expire($lockname, $lockexpire);//當對price寫入操作的這部分**的執行時間大於快取時間($lockexpire)時,依然有可能會產生併發。所以對price的操作要盡量放在前面(比如當sleep(10)的**放在set操作之前依然會產生併發)實際線上環境應該測試這部分**的執行時間,然後$lockexpire的值要大於這個執行時間

//開始對price進行讀寫

$price=$redis->get('price');

$price=$price+10;

sleep(5);

$redis->set($key,$price);

//鎖還沒過期就刪除 過期的沒必要刪除

if ($redis->ttl($lockname))

}else{

//如果不是以上情況 說明有人正在對price進行寫操作

echo 'please wait!';exit;

參考文章:

這種方法的缺點也很明顯,當有人正在寫操作時候,其他人都不能進行相關操作

3.可以使用佇列

將使用者的操作都存進乙個佇列中,然後用另乙個執行緒去消費這個佇列。這樣的好處就是每個使用者的操作都可以有效的操作。並且不會有併發操作的情況。

實際場景中應該視需求來決定要用什麼辦法。

redis解決併發問題

用redis處理高併發是個很常見的方式,因為redis的訪問效率很高 直接訪問記憶體 一般我們會用來處理 一瞬間的併發量。那如果要使用redis來進行高併發問題的解決的話,應注意以下幾點 1 首先我們要先知道,我們在儲存時,應使用redis的setnx方法,不應該使用set方法,因為setnx擁有原...

Redis高併發問題

商品搶購秒殺等活動 使用redis列表結構實現佇列資料結構,強拆的用rpush入隊,再用lpop出隊.redis宕機或者連線不上 解決方法 配置主從複製,配置哨兵模式,一旦發現主機宕機,讓下乙個從機當做主機。最壞的情況,只能關閉redis連線,去往資料庫連線。但由於資料量大,這樣sql資料庫也會宕掉...

php 處理併發問題

對於商品搶購等併發場景下,可能會出現超賣的現象,這時就需要解決併發所帶來的這些問題了 在php 語言中並沒有原生的提供併發的解決方案,因此就需要借助其他方式來實現併發控制。方案一 使用檔案鎖排它鎖 flock函式用於獲取檔案的鎖,這個鎖同時只能被乙個執行緒獲取到,其它沒有獲取到鎖的執行緒要麼阻塞,要...