最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

redis隊列和秒殺應用方式

 更新時間:2025年04月22日 09:41:23   作者:程序猿John  
這篇文章主要介紹了redis隊列和秒殺應用方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教

1.簡述

redis隊列一般用于緩解數(shù)據(jù)庫壓力 ,諸如秒殺,郵件群發(fā),消息推送等等

redis的加入能很好的 幫助系統(tǒng)中 各個模塊解耦。

而Redis不僅可作為緩存服務器,還可用作消息隊列。它的列表類型天生支持用作消息隊列。如下圖所示:

對于服務器減少io 壓力 有一定的幫助

2.秒殺的原理

秒殺基本原理比較簡單

用戶點擊搶購按鈕 -> 把uid 和時間存入redis的隊列中 -> 服務器中有一個入庫程序不停輪詢redis隊列是否有數(shù)據(jù) -> 如果有存入數(shù)據(jù)庫

這里面有2點需要注意一下:

  • 1. 插入隊列的時候 ,需要判斷庫傳,不能出現(xiàn)多插入
  • 2. 在入庫的時候 如果出現(xiàn)數(shù)據(jù)插入失敗的情況 需要進行回滾

3.秒殺的代碼實現(xiàn)

用戶操作秒殺:

header("Content-type: text/html; charset=utf-8");
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);

$redis_name= "miaosha";
//庫存
$nums = 10;
//用戶id
$user_id = $_GET['uid'];
if(($redis->llen($redis_name)) <  $nums ){
	$redis->lpush($redis_name,json_encode(array('uid'=>$user_id,'time'=>microtime())));
	echo $user_id."秒殺成功!";
	exit();
}else{
	echo "秒殺失敗!";
	exit();
}
$redis->close();

后臺處理秒殺隊列:

header("Content-type: text/html; charset=utf-8");
error_reporting(E_ALL);
require_once './db.php';
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);

$redis_name = "miaosha";

//數(shù)據(jù)庫
$configs =array('host'=>'127.0.0.1','port'=>'3306','user'=>'***','passwd'=>'','dbname'=>'test');
$mysql = new MMysql($configs);

//處理開始
while ($count = $redis->lLen($redis_name)) {
    $task = $redis->rpop($redis_name);
	
    $taskdata = json_decode($task, true);
	$data = array(
    	'uid'=>$taskdata['uid'],
    	'time'=>$taskdata['time'],
    );

	$rs = $mysql->insert('redis',$data);
	if(!$rs){
		//由于我們是在右邊取,所以如果數(shù)據(jù)插入失敗了要從左邊放回去(重新排隊),以免影響隊列中其他元素的處理
		$redis->lpush($redis_name,$task);
		echo "處理失敗<br>";
	}else{
		echo "處理成功<br>";
	}
    
	sleep(1);
}

$redis->close();

4.關于redis里的鎖

4.1 先說一下樂觀鎖

樂觀鎖,顧名思義,樂觀的認為數(shù)據(jù)不會被修改,只有當更新時才去判斷數(shù)據(jù)是否被修改過,通常用版本號或時間戳來實現(xiàn)。

redis中的事務通過watch和multi來實現(xiàn)。

WATCH命令可以監(jiān)控一個或多個鍵,一旦其中有一個鍵被修改(或刪除),之后的事務就不會執(zhí)行。監(jiān)控一直持續(xù)到EXEC命令(事務中的命令是在EXEC之后才執(zhí)行的,所以在MULTI命令后可以修改WATCH監(jiān)控的鍵值)

$redis = new Redis();
$redis->connect('127.0.0.1', 6379, 60);
 
 //
$tnums = $redis->get('goods_stock_nums');

//設置商品的庫存
if($tnums==0){
	echo "活動已經(jīng)結束,明天請早end!";
	exit();
}

//監(jiān)視該key
$redis->watch('goods_stock_nums');

//sleep(5);
//開啟事務
$redis->multi();
 
//修改庫存數(shù)
$redis->decr('goods_stock_nums');
 
//提交事務,如果在此期間有其他請求修改了該key,那么事務會失敗
if ($redis->exec()) {
    echo '搶購成功suc';
} else {
    echo '數(shù)據(jù)錯誤,請重新再試fail';
}

可以看到我在程序中加入了sleep(5) 這行代碼。

這是方便我在客戶端去實驗

如果我在運行上面這段代碼過程中,我用客戶端修改了這個值。

那么上面這段代碼就會失敗,返回 數(shù)據(jù)錯誤,請重新再試fail

4.2 再說一下 悲觀鎖

function getRedis()
{
    $redis = new Redis();
    $redis->connect('127.0.0.1', 6379, 60);
    return $redis;
}
 
function lock($key, $random)
{
    $redis = getRedis();
    return $redis->set($key, $random, ['nx', 'ex' => 3]);
}
 
function unlock($key, $random)
{
    $redis = getRedis();
    //使用lua腳本保證原子性
    $script = 'if redis.call("get",KEYS[1]) == ARGV[1] then return redis.call("del",KEYS[1]) else return 0 end';
    return $redis->eval($script, [$key, $random], 1);
}
 
function decrGoodsStockNums()
{
    $redis = getRedis();
 
    //獲取商品庫存數(shù)
    $ret = $redis->get('goods_stock_nums');
 
    if ($ret === false) {
        return false;
    }
 
    if ($ret <= 0) {
        return false;
    }
 
    $random = mt_rand();
    //先獲取鎖
    if (lock('goods_stock_nums_lock', $random)) {
        //修改庫存數(shù)
        $redis->decr('goods_stock_nums');
 
        //釋放鎖
        unlock('goods_stock_nums_lock', $random);
        return true;
    } else {
        usleep(100);
        decrGoodsStockNums();
    }
}
 
decrGoodsStockNums();

上面這段引用別人的代碼

但是這種鎖的機制還是不能保證事務的安全

總結

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關文章

  • Redis報錯UnrecognizedPropertyException: Unrecognized field問題

    Redis報錯UnrecognizedPropertyException: Unrecognized 

    在使用SpringBoot訪問Redis時,報錯提示識別不了屬性headPart,經(jīng)過排查,發(fā)現(xiàn)并非Serializable或getset方法問題,而是存在一個方法getHeadPart,但無headPart屬性,解決方案是將getHeadPart改為makeHeadPart
    2024-10-10
  • 詳解Redis開啟遠程登錄連接

    詳解Redis開啟遠程登錄連接

    本篇文章主要介紹了Redis開啟遠程登錄連接,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-05-05
  • 一文詳解Redis為什么一定要設置密碼原理

    一文詳解Redis為什么一定要設置密碼原理

    這篇文章主要為大家介紹了Redis為什么一定要設置密碼原理詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-03-03
  • redis GEO數(shù)據(jù)結構、實現(xiàn)附近商鋪功能實踐

    redis GEO數(shù)據(jù)結構、實現(xiàn)附近商鋪功能實踐

    文章介紹了Redis中的GEO命令及其用途,包括地理坐標存儲、距離計算、坐標轉換和位置搜索等功能,還分享了如何使用Redis實現(xiàn)查詢附近商鋪的功能,包括導入商鋪信息和根據(jù)類型及距離進行搜索
    2025-12-12
  • Redis底層數(shù)據(jù)結構SkipList的實現(xiàn)

    Redis底層數(shù)據(jù)結構SkipList的實現(xiàn)

    本文主要介紹了Redis底層數(shù)據(jù)結構SkipList的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-05-05
  • 淺談Redis在直播場景的實踐方案

    淺談Redis在直播場景的實踐方案

    這篇文章主要介紹了淺談Redis在直播場景的實踐方案,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-04-04
  • 帶你輕松掌握Redis分布式鎖

    帶你輕松掌握Redis分布式鎖

    這篇文章主要介紹了帶你輕松掌握Redis分布式鎖,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • Redis中3種特殊的數(shù)據(jù)類型(BitMap、Geo和HyperLogLog)

    Redis中3種特殊的數(shù)據(jù)類型(BitMap、Geo和HyperLogLog)

    這篇文章主要給大家介紹了關于Redis中3種特殊的數(shù)據(jù)類型(BitMap、GEOADD和GEODIST)的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧。
    2018-03-03
  • Redis中緩存和數(shù)據(jù)庫雙寫數(shù)據(jù)不一致的原因及解決方案

    Redis中緩存和數(shù)據(jù)庫雙寫數(shù)據(jù)不一致的原因及解決方案

    這篇文章主要介紹了Redis中緩存和數(shù)據(jù)庫雙寫數(shù)據(jù)不一致的原因及解決方案,文中通過圖文結合的方式講解的非常詳細,對大家的學習或工作有一定的幫助,需要的朋友可以參考下
    2024-03-03
  • Redis事務,Redis實現(xiàn)悲觀鎖,樂觀鎖方式

    Redis事務,Redis實現(xiàn)悲觀鎖,樂觀鎖方式

    文章介紹了Redis事務的概念、特點和執(zhí)行過程,區(qū)別于MySQL事務的ACID特性,詳細講解了未授權讀取、授權讀取、重復讀取和串行化四種隔離級別,并解析了悲觀鎖和樂觀鎖的定義與應用場景,最后闡述了Redis通過版本號實現(xiàn)樂觀鎖的機制
    2026-05-05

最新評論

竹北市| 寿阳县| 增城市| 汝城县| 上饶县| 阿勒泰市| 遂川县| 商丘市| 平阴县| 恩施市| 寻乌县| 贺州市| 青州市| 公主岭市| 常州市| 隆林| 图木舒克市| 微山县| 靖宇县| 玉树县| 桐柏县| 宿迁市| 石台县| 乌兰县| 龙川县| 交口县| 垫江县| 北票市| 会同县| 新乐市| 宜都市| 凤台县| 黑水县| 河曲县| 成武县| 酒泉市| 调兵山市| 大港区| 遂平县| 麻栗坡县| 沁源县|