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

Redis做預(yù)定庫存緩存功能設(shè)計使用

 更新時間:2022年04月01日 16:49:23   作者:HorstXu  
這篇文章主要為大家介紹了Redis做預(yù)定庫存緩存功能設(shè)計使用,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步早日升職加薪

最近在自己的工作中,把其中一個PHP項目的緩存從以前的APC緩存逐漸切換到Redis中,并且根據(jù)Redis所支持的數(shù)據(jù)結(jié)構(gòu)做了庫存維護功能。緩存是在業(yè)務(wù)層做的,準確講應(yīng)該是在MVC模型中Model的ORM里面。主要邏輯就是先查緩存,查不到的話再查數(shù)據(jù)庫。不過這些不是本文的主要內(nèi)容,下面我把庫存管理功能的緩存設(shè)計思路分享一下,希望能帶給大家一些收獲,有不足之處或者有更好方案的,也希望各位多多指教。

一、業(yè)務(wù)背景

為了略去我們公司項目背景,我決定把這次的問題類比成一個考卷上的問題。至于業(yè)務(wù)細節(jié),大家也無需關(guān)注~看題目就可以了:

假設(shè)你是某國最牛的收藏家,手里有各種價值連成的寶物。知道有一天,你覺得做收藏太沒意思了,打算把這些寶物賣掉換點現(xiàn)金。

不過把這些值錢的寶貝放在菜市場上賣實在太low了。在“互聯(lián)網(wǎng)+”時代,我們當(dāng)然要玩一些不一樣的賣法:在你名下有一棟300個房間的大樓(編號為001至300),每個房間放著一個密碼鎖保險箱,在下個月(12月1日至12月31日)的每一天,你都會挑選300件最好的“極品寶物”(也稱作A類寶物),分別放入這300個房間的保險箱里,每天每個房間放什么寶物已經(jīng)定好了,所有想買寶物的人必須至少提前一天在網(wǎng)上預(yù)定,到時候憑借預(yù)定碼自己打開保險箱取貨。沒有被預(yù)定的寶物將會被你收回,不再售賣。

要做這樣一個網(wǎng)絡(luò)預(yù)定系統(tǒng),它的前端界面大概是這樣的:

上圖中三個要填的控件,單擊后可以出現(xiàn)選擇框?,F(xiàn)在的問題是,一個房間只有一個寶物,不能被重復(fù)預(yù)定。所以當(dāng)買家選擇了寶物類型和房間號之后,在選擇預(yù)定日期時,要在日期選擇框給用戶一個提示。比如12月3日051號房間已被預(yù)定,現(xiàn)在又有另一位用戶選擇了051號房間,那么在彈出日期選擇框時,12月3日要置為不可選。如下圖(12月3日顯示為“缺”):

那么,這樣一個簡單的庫存系統(tǒng),如何在redis中存儲呢?

二、庫存管理方案(Redis)

最粗暴的想法是,我們的庫存其實就是一個很大的三維數(shù)組,第一維寶物類型,第二維房間號,第三維即預(yù)定日期。Redis支持5種存儲類型:String,Hash,List,Set,Sorted Set。目前的場景中Hash和Set類型都可以滿足要求,在此我們選擇使用Hash類型做存儲。

Redis的key設(shè)置為 寶物類型+房間號(例如 A:205,A代表極品寶物,205為房間號),Redis的value為hash類型,hash key為日期(例如 2016-12-05),hash value為true或false,表示已經(jīng)被預(yù)定或沒有被預(yù)定。用圖表示為:

如果A類寶物158房間在12月8日已經(jīng)被預(yù)定,則存儲為

Redis Key —— A:158

Redis Value —— hash table ['2016-12-08' => 1]

三、進階場景&庫存管理方案

你所推出的A類極品寶物很受歡迎,剛推出去不久即被預(yù)定出去很多。然而,動輒數(shù)十萬元的價格也讓很多有收藏興趣、卻沒那么富裕的中產(chǎn)階級望而卻步。于是,你又從自己的收藏中挑選出了比A類寶物稍次一些的B類寶物(也稱作“優(yōu)質(zhì)寶物”),價格更加親民。

由于B類寶物比A類寶物多一些,你打算換一種玩法,在這300個房間中,每個房間又放入了一個保險箱,這次,你每隔一個小時都會向300個房間的箱中各放入一件B類寶物,沒有被預(yù)定的寶物在這一個小時過后會被收回,換成下一個小時的寶物。買家預(yù)訂后,按照所預(yù)定的小時來取走寶物。對于B類寶物,你的預(yù)定系統(tǒng)會多了一個選項,即取貨時間。如下圖:

現(xiàn)在由于多了一個預(yù)定條件(取貨時間),那在做庫存存儲的時候,粗暴的方式想一下,庫存其實就是一個大的四維數(shù)組。第一維寶物類型,第二維房間號,第三維預(yù)定日期,第四維取貨時間。在Redis中怎樣存儲這類寶物呢?

其實仔細想一下,在存儲A類極品寶物的時候,我們在Redis中的存儲是有浪費維度的情況的,

當(dāng)時hashValue只存了一個true表示有預(yù)定,這個維度其實是被浪費掉了??紤]到取貨時間全是整點,一整天也就是0至1點,1至2點,……,23至24點共計24種情況,所以我們完全可以使用二進制整數(shù)表示被預(yù)定的時間。例如1表示0至1點,2表示1至2點,4表示2至3點,……,

8388608 (= 2^23)表示23至24點。多個時間段被預(yù)定,只需要將數(shù)值取邏輯或操作即可。

這樣,我們的Redis結(jié)構(gòu)變成了這樣子:

例如,B類寶物103房間,12月5日和6日的上午8點至12點被預(yù)定,在redis中存儲為

Redis Key  —— B:103

Redis Value —— hash table ['2016-12-05' => 3840, '2016-12-06' => 3840]

對于B類寶物,在做新增預(yù)定時,需要注意先將原有的hash value取出,和新的預(yù)定取貨時間做邏輯或操作,然后再把結(jié)果寫回Redis中,而不能像A類寶物一樣直接調(diào)用hSet去設(shè)置hash value;取消預(yù)定時,要注意先將原有的hash value取出,把要取消的時間段從hash value中扣除掉(異或+邏輯與操作),然后重新將剩余的已預(yù)訂取貨時間寫回Redis中,而不能直接調(diào)用hDel去刪除。

四、再次進階&庫存管理方案

自從推出了B類寶物之后,你的生意又比以往火爆了許多。于是新的需求又來了,現(xiàn)在有大量的游客、學(xué)生黨等沒什么豐厚積蓄的人表示對你的寶物非常感興趣,來這個城市旅游的人都希望帶一些紀念品回去。然而,B類寶物的價格雖然比A類便宜一些,對于這些人來講還是有點貴。于是,你決定把自己余量最多的實惠寶物(C類寶物)拿出來售賣。

這部分寶物數(shù)量是最多的,于是你在這300個房間中,每個房間新增了100個寶箱,專門用于存放C類寶物。這100個寶箱分別被編號為1號,2號,……,100號。同樣的,每天的每個小時,你都會向這300個房間中,每個房間的100個寶箱中分別放入一件C類寶物(也就意味著,整個大樓每小時C類寶物會更新30000件)。如果沒有人預(yù)定,則下一個小時寶物更換。終于,這下可以滿足所有人的需求了。

對于C類寶物,你的預(yù)定界面成了下面的樣子:

我們又多了一個預(yù)定條件。此時,又面臨著庫存存儲的問題。照例,這個庫存其實就是一個大的五維數(shù)組,寶物類型、房間號、預(yù)定日期、取貨時間、寶箱編號各自占有一個維度。不過前面我們的Redis各個維度基本上已經(jīng)占滿了,這次應(yīng)該怎么存儲呢?

這次的Redis庫存存儲必須要結(jié)合業(yè)務(wù)特點來了。首先,寶箱編號和取貨時間這兩個維度,能取的值范圍并不太多,寶箱編號只有100個,只要把hash value變成一個長度為100的數(shù)組,數(shù)組的每個位置都存有INT類型表示的取貨時間即可。然而hash value只能是string……于是乎,只好做一個數(shù)組的序列化操作,讀取的時候再反序列化回來即可。好在長度只有100,序列化效率并不會成為系統(tǒng)的瓶頸。

例如,C類寶物,12月23日、24日,258房間,97和99號寶箱在11點至13點被預(yù)定,則存儲為:

Redis Key  —— B:103

Redis Value —— hash table ['2016-12-05' => 3840, '2016-12-06' => 3840]

其中6144用二進制表示為‘110000000000’,hash value為數(shù)組序列化以后的字符串,實際項目中可以使用json格式。好了,現(xiàn)在Redis對于三種寶物的存儲都有了。

對于C類寶物,在用戶取消預(yù)定、新增預(yù)定時,同樣不能簡單地調(diào)用hSet和hDel進行覆蓋設(shè)置和刪除,要取出已經(jīng)預(yù)定的情況,與已經(jīng)預(yù)定的取貨時間做位運算。

五、存儲優(yōu)化

庫存理論上就是一個多維數(shù)組,我們所做的主要工作就是怎樣把各個維度合理的存儲起來,并能夠方便地進行增加、刪除、查詢操作。從節(jié)約使用內(nèi)存的角度講,在最開始還沒有任何人預(yù)定的時候,Redis整個可以是空的,對于A類寶物來說,hash value等于false和根本不存在對應(yīng)的redis key或hash key是等效的。

另外,寶物類型和房間號合起來做redis key,會導(dǎo)致我們在redis中和寶物庫存相關(guān)的key的數(shù)量比較多,為了方便統(tǒng)一管理這些key,可以再增加一條redis緩存,專門用來存儲和寶物庫存相關(guān)的所有redis key值,如下圖所示。需要注意的是,這次我們并不需要hash數(shù)據(jù)類型了,set類型就已經(jīng)足夠,增刪改查復(fù)雜度都是O(1)。里面存儲了所有redis中已經(jīng)存在的庫存key值。

這么做的一個好處是,萬一哪天碰到一些特殊情況,需要把所有庫存相關(guān)緩存全部清空的話,我們可以很容易地取出所有的庫存key并做刪除操作。另外一個好處是,給我們提供了繼續(xù)擴展的思路……設(shè)想一下,現(xiàn)在最復(fù)雜的情況是C類寶物,一共5個維度。假設(shè)未來,你不再使用一幢樓的300個房間去售賣寶物,而是多幢樓,那么用戶在下訂單的時候又要多出一個維度——樓棟編號。碰到這種情況,我們完全可以將這個多出來的庫存Key集合退化為樓棟編號來使用,保證了可能出現(xiàn)的更復(fù)雜情況下的擴展性。

在做了這次擴展之后,每次新增預(yù)定記錄時,需要注意檢測庫存key集合中是否已經(jīng)存在對應(yīng)的redis key值,如果不存在需要將redis key值加入庫存key集合中。刪除操作也類似。

六、總結(jié)

上面使用了循序漸進的方法講述了一下問題,不過現(xiàn)實的場景中,這三種寶物類型在我們的業(yè)務(wù)中是同時存在的。上面的設(shè)計保持了三種寶物類型存儲上的統(tǒng)一性。如果只考慮A類寶物的話,庫存只有三個維度,其實完全不必使用hash數(shù)據(jù)類型來存儲,set類型就足夠了。

我們存儲這些預(yù)定情況的主要目的,就是為了方便快速地查到庫存沖突情況。比如有人已經(jīng)定了12月3日,59號房間的A類寶物,那又有另外一個人想預(yù)定一樣的日期、房間的A類寶物時,通過內(nèi)存中的庫存查詢,我們可以很方便地告訴客戶,該庫存已經(jīng)被其他人搶先預(yù)定了。

以上就是我在業(yè)務(wù)中碰到的一個緩存設(shè)計的小問題,不吝賜教!

以上就是Redis做預(yù)定庫存緩存功能設(shè)計使用的詳細內(nèi)容,更多關(guān)于Redis預(yù)定庫存緩存設(shè)計的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Redis安全策略詳解

    Redis安全策略詳解

    緩存穿透是指當(dāng)用戶在查詢一條數(shù)據(jù)的時候,而此時數(shù)據(jù)庫和緩存卻沒有關(guān)于這條數(shù)據(jù)的任何記錄,而這條數(shù)據(jù)在緩存中沒找到就會向數(shù)據(jù)庫請求獲取數(shù)據(jù)。用戶拿不到數(shù)據(jù)時,就會一直發(fā)請求,查詢數(shù)據(jù)庫,這樣會對數(shù)據(jù)庫的訪問造成很大的壓力
    2022-07-07
  • Redis中的bitmap詳解

    Redis中的bitmap詳解

    BitMap是通過一個bit位來表示某個元素對應(yīng)的值或者狀態(tài),其中的key就是對應(yīng)元素本身。我們知道8個bit可以組成一個Byte,所以bitmap本身會極大的節(jié)省儲存空間,下面通過本文給大家介紹Redis中的bitmap知識,感興趣的朋友一起看看吧
    2021-10-10
  • redis常用命令小結(jié)

    redis常用命令小結(jié)

    這篇文章主要介紹了redis的一些常用命令,需要的朋友可以參考下
    2014-06-06
  • Redis優(yōu)惠券秒殺解決方案

    Redis優(yōu)惠券秒殺解決方案

    這篇文章主要介紹了Redis解決優(yōu)惠券秒殺應(yīng)用案例,本文先講了搶購問題,指出其中會出現(xiàn)的多線程問題,提出解決方案采用悲觀鎖和樂觀鎖兩種方式進行實現(xiàn),然后發(fā)現(xiàn)在搶購過程中容易出現(xiàn)一人多單現(xiàn)象,需要的朋友可以參考下
    2022-12-12
  • Redis設(shè)置Hash數(shù)據(jù)類型的過期時間

    Redis設(shè)置Hash數(shù)據(jù)類型的過期時間

    在Redis中,我們可以使用Hash數(shù)據(jù)結(jié)構(gòu)來存儲一組鍵值對,而有時候,我們可能需要設(shè)置這些鍵值對的過期時間,本文主要介紹了Redis設(shè)置Hash數(shù)據(jù)類型的過期時間,具有一定的參考價值,感興趣的可以了解一下
    2024-01-01
  • Redis實現(xiàn)分布式鎖的五種方法詳解

    Redis實現(xiàn)分布式鎖的五種方法詳解

    在分布式架構(gòu)中,我們同樣會遇到數(shù)據(jù)共享操作問題,本文章使用Redis來解決分布式架構(gòu)中的數(shù)據(jù)一致性問題,需要的小伙伴可以參考一下
    2022-06-06
  • Redis+Caffeine實現(xiàn)分布式二級緩存組件實戰(zhàn)教程

    Redis+Caffeine實現(xiàn)分布式二級緩存組件實戰(zhàn)教程

    這篇文章主要介紹了Redis+Caffeine實現(xiàn)分布式二級緩存組件實戰(zhàn)教程,介紹了分布式二級緩存的優(yōu)勢,使用組件的方法,通過示例代碼給大家介紹的非常詳細,需要的朋友可以參考下
    2022-08-08
  • 一篇文章揭秘Redis的磁盤持久化機制

    一篇文章揭秘Redis的磁盤持久化機制

    這篇文章主要給大家介紹了如何通過一篇文章揭秘Redis的磁盤持久化機制的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家學(xué)習(xí)或者使用Redis具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • 基于Redis分布式鎖的實現(xiàn)代碼

    基于Redis分布式鎖的實現(xiàn)代碼

    這篇文章主要介紹了Redis分布式鎖的實現(xiàn),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-05-05
  • Redis的常見四種部署方案

    Redis的常見四種部署方案

    這篇文章介紹Reids最為常見的四種部署模式,其實Reids和數(shù)據(jù)庫的集群模式差不多,可以分為 Redis單機模式部署、Redis主從模式部署、Redis哨兵模式部署、Cluster集群模式部署,其他的部署方式基本都是圍繞以下幾種方式在進行調(diào)整到適應(yīng)的生產(chǎn)環(huán)境,感興趣的朋友一起看看吧
    2023-11-11

最新評論