欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

redis隊列和秒殺應(yīng)用方式

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

1.簡述

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

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

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

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

2.秒殺的原理

秒殺基本原理比較簡單

用戶點擊搶購按鈕 -> 把uid 和時間存入redis的隊列中 -> 服務(wù)器中有一個入庫程序不停輪詢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.關(guān)于redis里的鎖

4.1 先說一下樂觀鎖

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

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

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

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

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

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

//sleep(5);
//開啟事務(wù)
$redis->multi();
 
//修改庫存數(shù)
$redis->decr('goods_stock_nums');
 
//提交事務(wù),如果在此期間有其他請求修改了該key,那么事務(wù)會失敗
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();

上面這段引用別人的代碼

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

總結(jié)

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

相關(guān)文章

  • Redis全量復(fù)制與部分復(fù)制示例詳解

    Redis全量復(fù)制與部分復(fù)制示例詳解

    這篇文章主要給大家介紹了關(guān)于Redis全量復(fù)制與部分復(fù)制的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家學(xué)習(xí)或者使用Redis爬蟲具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-08-08
  • Redis數(shù)據(jù)一致性詳解

    Redis數(shù)據(jù)一致性詳解

    文章主要討論了分布式系統(tǒng)中的數(shù)據(jù)一致性模型、緩存使用場景以及數(shù)據(jù)同步策略,一致性模型包括強一致性、弱一致性和最終一致性,緩存使用場景主要在高并發(fā)讀取數(shù)據(jù)時提升性能,數(shù)據(jù)同步策略分為先刪除緩存再更新數(shù)據(jù)庫和先更新數(shù)據(jù)庫再刪除緩存兩種
    2024-11-11
  • redis監(jiān)聽key過期事件的詳細步驟

    redis監(jiān)聽key過期事件的詳細步驟

    本文主要介紹了redis監(jiān)聽key過期事件的詳細步驟,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-08-08
  • redis中RDB(Redis Data Base)的機制

    redis中RDB(Redis Data Base)的機制

    本文主要介紹了redis中RDB(Redis Data Base)的機制,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • redis的hash類型操作方法

    redis的hash類型操作方法

    Hash 是一個 String 類型的 field(字段) 和 value(值) 的映射表,hash 特別適合用于存儲對象,這篇文章主要介紹了redis的hash類型的詳解,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-06-06
  • Redis五種數(shù)據(jù)類型詳解

    Redis五種數(shù)據(jù)類型詳解

    Redis是基于內(nèi)存的 K-V 數(shù)據(jù)庫,常用于緩存、消息隊列,分布式鎖等場景,并且提供了常見的數(shù)據(jù)結(jié)構(gòu):字符串、哈希、列表、集合、帶排序的集合,本文主要介紹了Redis的五種數(shù)據(jù)類型,感興趣的小伙伴可以參考閱讀本文
    2023-04-04
  • redis分布式鎖之可重入鎖的實現(xiàn)代碼

    redis分布式鎖之可重入鎖的實現(xiàn)代碼

    相信大家都知道可重入鎖的作用防止在同一線程中多次獲取鎖而導(dǎo)致死鎖發(fā)生,本文通過幾個例子給大家分享redis分布式鎖之可重入鎖的實現(xiàn)代碼,對redis分布式鎖的相關(guān)知識,感興趣的朋友一起看看吧
    2021-05-05
  • Redis分片集群的實現(xiàn)

    Redis分片集群的實現(xiàn)

    Redis 分片集群是一種將 Redis數(shù)據(jù)庫分散到多個節(jié)點上的方式,以提供更高的性能和可伸縮性,本文主要介紹了Redis分片集群的實現(xiàn),具有一定的參考價值,感興趣的可以了解一下
    2025-04-04
  • Redis大key和多key拆分的解決方案

    Redis大key和多key拆分的解決方案

    大key會導(dǎo)致內(nèi)存使用過高,多key可能導(dǎo)致查詢效率低下,本文主要介紹了Redis大key和多key拆分的解決方案,具有一定的參考價值,感興趣的可以了解一下
    2024-03-03
  • Redis fork進程分配不到內(nèi)存解決方案

    Redis fork進程分配不到內(nèi)存解決方案

    這篇文章主要介紹了Redis fork進程分配不到內(nèi)存解決方案,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-11-11

最新評論