国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Redis專題-秒殺

這篇具有很好參考價值的文章主要介紹了Redis專題-秒殺。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

Redis專題-并發(fā)/秒殺

開局一張圖,內(nèi)容全靠“編”。

昨天晚上在群友里看到有人在討論庫存并發(fā)的問題,看到這里我就決定寫一篇關(guān)于redis秒殺的文章。

Redis專題-秒殺,redis,數(shù)據(jù)庫,緩存Redis專題-秒殺,redis,數(shù)據(jù)庫,緩存

1、理論部分

我們看看一般我們庫存是怎么出問題的

Redis專題-秒殺,redis,數(shù)據(jù)庫,緩存

其實redis提供了兩種解決方案:加鎖和原子操作

1.1、加鎖

加鎖:其實非常常見,讀取數(shù)據(jù)前,客戶端先獲取鎖,再操作。
當(dāng)客戶端獲得鎖后,一直持有直到客戶端完成操作,再釋放。

怎么操作呢,客戶端使用分布式鎖來獲取鎖,(使用redis或者zookeeper來實現(xiàn)一個分布式鎖)以商品的維度來加鎖,在獲取到鎖的線程中,按順序執(zhí)行商品的庫存查詢和扣減,同時實現(xiàn)了順序性和原子性。

Redis專題-秒殺,redis,數(shù)據(jù)庫,緩存

但是,但是,有問題:
1、如果使用redis來實現(xiàn)分布式鎖,那么鎖的時效性是個問題。太短了,業(yè)務(wù)還沒跑完鎖就釋放了。太長了,如果異常,其他業(yè)務(wù)就一直阻塞等著自動釋放。

2、如果使用zookeeper,確實不用擔(dān)心鎖釋放問題(臨時節(jié)點),而且一致性好,但是性能不高。ZK中創(chuàng)建和刪除節(jié)點只能通過Leader服務(wù)器來執(zhí)行,然后Leader服務(wù)器還需要將數(shù)據(jù)同不到所有的Follower機器上,這樣頻繁的網(wǎng)絡(luò)通信,性能的短板是非常突出的。(挖坑??后續(xù)寫一個redis和zookeeper實現(xiàn)分布式鎖的文章)

所以。。繼續(xù)往下看。。

1.2、原子操作

原子操作:執(zhí)行過程中保持原子性操作,而原子性操作是不需要加鎖的,也就是無鎖操作。所以既保證了并發(fā)也不會減少系統(tǒng)并發(fā)性能。

redis的原子操作其實也有兩種方式:
1、單命令操作:多個操作在redis中一個操作完成
2、lua:多個操作寫成lua腳本,以原子性方式執(zhí)行單個lua腳本

1.2.1、INCR/DECR

Redis 是使用單線程來串行處理客戶端的請求操作命令的,所以,當(dāng) Redis 執(zhí)行某個命令操作時,其他命令是無法執(zhí)行的,這相當(dāng)于命令操作是互斥執(zhí)行的。

Redis 的單個命令操作可以原子性地執(zhí)行,但是在實際應(yīng)用中,數(shù)據(jù)修改時可能包含多個操作,至少包括讀數(shù)據(jù)、數(shù)據(jù)增減、寫回數(shù)據(jù)三個操作,這顯然就不是單個命令操作了,那該怎么辦呢?

Redis提供INCR/DECR,將讀數(shù)據(jù)、數(shù)據(jù)增減、寫回數(shù)據(jù)三個操作合并為了一個,可以對數(shù)據(jù)進行增值 / 減值操作,而且它們本身就是單個命令操作,所以本身具有互斥性??梢灾苯訋椭覀冞M行并發(fā)控制。

// 將商量id的庫存減1
DECR id

是的,就是這么簡單就搞定了扣減庫存。

1.2.2、Lua腳本

Redis 會把整個 Lua 腳本作為一個整體執(zhí)行,在執(zhí)行的過程中不會被其他命令打斷,從而保證了 Lua 腳本中操作的原子性。

將要執(zhí)行的操作編寫到一個 Lua 腳本中,使用 Redis 的 EVAL 命令來執(zhí)行腳本。

原生 EVAL 方法的使用語法如下:

EVAL script numkeys key [key ...] arg [arg ...]

script 是我們 Lua 腳本的字符串形式,numkeys 是我們要傳入的參數(shù)數(shù)量,key 是我們的入?yún)ⅲ梢詡魅攵鄠€,arg 是額外的入?yún)ⅰ?/p>

但這種方式需要每次都傳入 Lua 腳本字符串,不僅浪費網(wǎng)絡(luò)開銷,同時 Redis 需要每次重新編譯 Lua 腳本,對于我們追求性能極限的系統(tǒng)來說,不是很完美。所以這里就要說到另一個命令 EVALSHA 了,原生語法如下:

EVALSHA sha1 numkeys key [key ...] arg [arg ...]

可以看到其語法與 EVAL 類似,不同的是這里傳入的不是腳本字符串,而是一個加密串 sha1。這個 sha1 是從哪來的呢?它是通過另一個命令 SCRIPT LOAD 返回的,該命令是預(yù)加載腳本用的,語法為:

SCRIPT LOAD script

將 Lua 腳本先存儲在 Redis 中,并返回一個 sha1,下次要執(zhí)行對應(yīng)腳本時,只需要傳入 sha1 即可執(zhí)行對應(yīng)的腳本。這完美地解決了 EVAL 命令存在的弊端,所以我們這里也是基于 EVALSHA 方式來實現(xiàn)的。

-- 調(diào)用Redis的get指令,查詢活動庫存,其中KEYS[1]為傳入的參數(shù)1,即庫存key
local c_s = redis.call('get', KEYS[1])
-- 判斷活動庫存是否充足,其中KEYS[2]為傳入的參數(shù)2,即當(dāng)前搶購數(shù)量
if not c_s or tonumber(c_s) < tonumber(KEYS[2]) then
   return 0
end
-- 如果活動庫存充足,則進行扣減操作。其中KEYS[2]為傳入的參數(shù)2,即當(dāng)前搶購數(shù)量
redis.call('decrby',KEYS[1], KEYS[2])
return 1

我們可以將腳本先寫在配置中心,代碼執(zhí)行的時候就去拉取最新的sha1?;蛘叽a里面寫死。

當(dāng)然這個腳本也可以擴展,比如加上IP限制等等。但是太多操作放在Lua里也會降低redis的并發(fā)性能,所以非并發(fā)控制就不寫到lua了。

理論看完了,實操一下吧

2、Talk is cheap. Show me the code

2.1、安裝redis

跳過,不會安裝的出門右拐。

我自己用podman。

podman run -p 6379:6379 --name my_redis --privileged=true -v D:\podman\redis\conf\redis.conf:/etc/redis/redis.conf  -v D:\podman\redis\data:/data -d docker.io/library/redis redis-server /etc/redis/redis.conf --appendonly yes

2.2、代碼

在下.neter,就寫C#代碼了

[ApiController]
    [Route("[controller]")]
    public class HomeController : ControllerBase
    {
        private static string _redisConnection = "localhost:6379";
        private static ConnectionMultiplexer _connMultiplexer;
         
        private string _redisScript = @"local c_s = redis.call('get', KEYS[1])
                                        if not c_s or tonumber(c_s) < tonumber(KEYS[2]) then
                                           return 0
                                        end
                                        redis.call('decrby',KEYS[1], KEYS[2])
                                          return 1";
        private string _sha1 = string.Empty;
        /// <summary>
        /// 鎖
        /// </summary>
        private static readonly object Locker = new object();

        private static int _count = 0;
        private static int _rushToPurchaseCount = 0;

        /// <summary>
        /// 獲取 Redis 連接對象
        /// </summary>
        /// <returns></returns>
        private IConnectionMultiplexer GetConnectionRedisMultiplexer()
        {
            if ((_connMultiplexer == null) || !_connMultiplexer.IsConnected)
            {
                lock (Locker)
                {
                    if ((_connMultiplexer == null) || !_connMultiplexer.IsConnected)
                    {
                        _connMultiplexer = ConnectionMultiplexer.Connect(_redisConnection);
                    } 
                }
            }
            return _connMultiplexer;
        }
        
        [HttpPost("/Init")]
        public IActionResult Init()
        {
            GetConnectionRedisMultiplexer();
            return Ok();
        }
        [HttpPost]
        public async Task<IActionResult> Post()
        {
            System.Diagnostics.Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start(); 
            var db = _connMultiplexer.GetDatabase();
            var cache = db.ScriptEvaluateAsync(_redisScript,
                new RedisKey[] { "key999", "1" });

            var results = (string[]?)await cache;
            
            if (results[0] == "1")
            {
                Interlocked.Increment(ref _rushToPurchaseCount);
                Console.WriteLine($"恭喜您搶到了,{_rushToPurchaseCount}");
            }
            else
            {
                Console.WriteLine("很遺憾,您沒有搶到");
            }
            return Ok();
        }
    }

我們在redis中新增5個庫存

Redis專題-秒殺,redis,數(shù)據(jù)庫,緩存

配置一下Jmeter,100個線程3秒內(nèi)跑完

Redis專題-秒殺,redis,數(shù)據(jù)庫,緩存

Redis專題-秒殺,redis,數(shù)據(jù)庫,緩存

家人們!準備開槍!3!2!1!上鏈接!??????

Redis專題-秒殺,redis,數(shù)據(jù)庫,緩存

讓我們恭喜這5位大冤種??

Jmeter聚合報告Redis專題-秒殺,redis,數(shù)據(jù)庫,緩存

redis庫存為0Redis專題-秒殺,redis,數(shù)據(jù)庫,緩存

好了,到這里就先結(jié)束了。拜拜

github StackExchange手把手帶你搭建秒殺系統(tǒng)-不差毫厘:秒殺的庫存與限購Redis 核心技術(shù)與實戰(zhàn)-無鎖的原子操作:Redis如何應(yīng)對并發(fā)訪問?.Net Core使用分布式緩存Redis:Lua腳本文章來源地址http://www.zghlxwxcb.cn/news/detail-659890.html

到了這里,關(guān)于Redis專題-秒殺的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • Redis如何保證緩存和數(shù)據(jù)庫一致性?

    現(xiàn)在我們在面向增刪改查開發(fā)時,數(shù)據(jù)庫數(shù)據(jù)量大時或者對響應(yīng)要求較快,我們就需要用到Redis來拿取數(shù)據(jù)。 Redis:是一種高性能的內(nèi)存數(shù)據(jù)庫,它將數(shù)據(jù)以鍵值對的形式存儲在內(nèi)存中,具有讀寫速度快、支持多種數(shù)據(jù)類型、原子性操作、豐富的特性等優(yōu)勢。 優(yōu)勢: 性能極高

    2024年01月16日
    瀏覽(41)
  • Redis---數(shù)據(jù)庫和緩存如何保證一致性?

    用「讀 + 寫」請求的并發(fā)的場景來分析: 假如某個用戶數(shù)據(jù)在緩存中不存在,請求 A 讀取數(shù)據(jù)時從數(shù)據(jù)庫中查詢到年齡為 20,在未寫入緩存中時另一個請求 B 更新數(shù)據(jù)。它更新數(shù)據(jù)庫中的年齡為 21,并且清空緩存。這時請求 A 把從數(shù)據(jù)庫中讀到的年齡為 20 的數(shù)據(jù)寫入到緩存

    2024年01月24日
    瀏覽(27)
  • Redis如何保障緩存與數(shù)據(jù)庫的數(shù)據(jù)一致性問題?

    Redis如何保障緩存與數(shù)據(jù)庫的數(shù)據(jù)一致性問題?

    目錄 一.最經(jīng)典的數(shù)據(jù)庫加緩存的雙寫雙刪模式 二. 高并發(fā)場景下的緩存+數(shù)據(jù)庫雙寫不一致問題分析與解決方案設(shè)計 三、上面高并發(fā)的場景下,該解決方案要注意的問題 1.1 Cache Aside Pattern概念以及讀寫邏輯 (1)讀的時候,先讀緩存,緩存沒有的話,那么就讀數(shù)據(jù)庫,然后取

    2023年04月21日
    瀏覽(29)
  • Springboot+Redis:實現(xiàn)緩存 減少對數(shù)據(jù)庫的壓力

    Springboot+Redis:實現(xiàn)緩存 減少對數(shù)據(jù)庫的壓力

    ????歡迎光臨,終于等到你啦???? ??我是蘇澤,一位對技術(shù)充滿熱情的探索者和分享者。???? ??持續(xù)更新的專欄 Redis實戰(zhàn)與進階 本專欄講解Redis從原理到實踐 這是蘇澤的個人主頁可以看到我其他的內(nèi)容哦???? 努力的蘇澤 http://suzee.blog.csdn.net/ ? 目錄 緩存如何實現(xiàn)?

    2024年03月24日
    瀏覽(19)
  • 數(shù)據(jù)庫緩存服務(wù)——NoSQL之Redis配置與優(yōu)化

    數(shù)據(jù)庫緩存服務(wù)——NoSQL之Redis配置與優(yōu)化

    目錄 一、緩存概念 1.1 系統(tǒng)緩存 1.2 緩存保存位置及分層結(jié)構(gòu) 1.2.1 DNS緩存 1.2.2 應(yīng)用層緩存 1.2.3 數(shù)據(jù)層緩存 1.2.4 硬件緩存 二、關(guān)系型數(shù)據(jù)庫與非關(guān)系型數(shù)據(jù)庫 2.1 關(guān)系型數(shù)據(jù)庫 2.2 非關(guān)系型數(shù)據(jù)庫 2.3 關(guān)系型數(shù)據(jù)庫和非關(guān)系型數(shù)據(jù)庫區(qū)別: 2.4 非關(guān)系型數(shù)據(jù)庫產(chǎn)生背景 2.5 總結(jié)

    2024年02月15日
    瀏覽(24)
  • Redis數(shù)據(jù)庫 | 發(fā)布訂閱、主從復(fù)制、哨兵模式、緩存雪崩

    Redis數(shù)據(jù)庫 | 發(fā)布訂閱、主從復(fù)制、哨兵模式、緩存雪崩

    ??wei_shuo的個人主頁 ??wei_shuo的學(xué)習(xí)社區(qū) ??Hello World ! Redis 發(fā)布訂閱 (pub/sub) 是一種消息通信模式:發(fā)送者 (pub) 發(fā)送消息,訂閱者 (sub) 接收消息 Redis 客戶端可以訂閱任意數(shù)量的頻道 Redis主從復(fù)制是指在Redis中設(shè)置一個主節(jié)點(Master)和一個或多個從節(jié)點(Slave),

    2024年02月15日
    瀏覽(25)
  • Redis緩存MySQL數(shù)據(jù)庫存儲二者如何保證數(shù)據(jù)一致性

    在大型互聯(lián)網(wǎng)應(yīng)用中,由于數(shù)據(jù)庫讀寫頻繁、壓力大等原因,我們通常會使用緩存來減少數(shù)據(jù)庫的訪問次數(shù),提高系統(tǒng)的性能。而Redis作為一個高性能的內(nèi)存數(shù)據(jù)庫,成為了緩存的首選方案之一。但是,緩存和數(shù)據(jù)庫之間存在數(shù)據(jù)一致性的問題,如何解決這個問題呢?本文將

    2023年04月19日
    瀏覽(27)
  • redis面試題目-如何保證數(shù)據(jù)庫與緩存的數(shù)據(jù)一致性

    原視頻:https://www.bilibili.com/video/BV1Km4y1r75f?p=62vd_source=fa75329ae3880aa55609265a0e9f5d34 由于緩存和數(shù)據(jù)庫是分開的,無法做到原子性的同時進行數(shù)據(jù)修改,可能出現(xiàn)緩存更新失敗,或者數(shù)據(jù)庫更新失敗的情況,這時候會出現(xiàn)數(shù)據(jù)不一致,影響前端業(yè)務(wù) 先更新數(shù)據(jù)庫,再更新緩存。緩

    2024年02月05日
    瀏覽(27)
  • Redis 緩存與數(shù)據(jù)庫雙寫不一致如何解決

    Redis緩存與數(shù)據(jù)庫雙寫不一致是一個常見的挑戰(zhàn),但可以通過一些方法來解決或減輕這種不一致性。以下是一些可能的解決方案: 事務(wù)處理: 在進行緩存和數(shù)據(jù)庫雙寫時,確保它們被包含在同一事務(wù)中。這可以通過使用支持事務(wù)的數(shù)據(jù)庫和Redis事務(wù)來實現(xiàn)。這樣,要么兩者同

    2024年01月21日
    瀏覽(24)
  • 如何保證Redis緩存和數(shù)據(jù)庫的一致性問題

    熟練掌握Redis緩存技術(shù)? 那么請問Redis緩存中有幾種讀寫策略,又是如何保證與數(shù)據(jù)庫的一致性問題 今天來聊一聊常用的三種緩存讀寫策略 首先我們來思考一個問題 寫 先更新緩存 再更新數(shù)據(jù)庫 首先如果緩存更新成功但數(shù)據(jù)庫更新失敗,會導(dǎo)致數(shù)據(jù)不一致的問題 其次當(dāng)請求

    2024年02月14日
    瀏覽(23)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包