主頁(yè) > 知識(shí)庫(kù) > 從一個(gè)小需求感受Redis的獨(dú)特魅力(需求設(shè)計(jì))

從一個(gè)小需求感受Redis的獨(dú)特魅力(需求設(shè)計(jì))

熱門(mén)標(biāo)簽:Linux服務(wù)器 網(wǎng)站排名優(yōu)化 鐵路電話(huà)系統(tǒng) AI電銷(xiāo) 百度競(jìng)價(jià)排名 呼叫中心市場(chǎng)需求 地方門(mén)戶(hù)網(wǎng)站 服務(wù)外包

分享一個(gè)簡(jiǎn)單的小需求應(yīng)該怎么設(shè)計(jì)實(shí)現(xiàn)以及有關(guān)Redis的使用

Redis在實(shí)際應(yīng)用中使用的非常廣泛,本篇文章就從一個(gè)簡(jiǎn)單的需求說(shuō)起,為你講述一個(gè)需求是如何從頭到尾開(kāi)始做的,又是如何一步步完善的。之前寫(xiě)過(guò)一篇《如何實(shí)現(xiàn)頁(yè)面廣告隨時(shí)上下線(xiàn)、過(guò)期自動(dòng)下線(xiàn)及到時(shí)自動(dòng)上線(xiàn)》,也涉及到了Redis在項(xiàng)目中的實(shí)際應(yīng)用,有興趣的可以看一下。

需求

設(shè)定,現(xiàn)在我們有一個(gè)APP,產(chǎn)品新提出一個(gè)叫“程序員樹(shù)洞”的功能,具體功能就不說(shuō)了,其中這個(gè)功能有一點(diǎn)需要做的是在使用該功能時(shí),如果是首次進(jìn)入會(huì)展示一個(gè)協(xié)議頁(yè)面,用戶(hù)需要勾選后點(diǎn)確定才能進(jìn)入功能,此后再進(jìn)該功能,不再顯示協(xié)議頁(yè)直接進(jìn)入該功能。如下圖所示,

原型圖

需求分析

需求就是這么的簡(jiǎn)單,我們來(lái)分析一下。

1、用戶(hù)點(diǎn)擊該功能時(shí)前端需要知道該給用戶(hù)顯示哪個(gè)頁(yè)面,這一步需要請(qǐng)求后端接口,后臺(tái)告訴前端這個(gè)用戶(hù)有沒(méi)有同意過(guò)協(xié)議。

2、用戶(hù)勾選協(xié)議點(diǎn)確定,后端需要記錄這步操作(記錄用戶(hù)已經(jīng)同意協(xié)議),這一步需在點(diǎn)確定時(shí)前端請(qǐng)求后端接口。

概要設(shè)計(jì)

前面需求分析里說(shuō)了,后端需要告訴前端用戶(hù)有沒(méi)有統(tǒng)一過(guò)協(xié)議,所以后端需要把這個(gè)信息記錄下來(lái),最好是記錄到數(shù)據(jù)庫(kù)保存,那就需要一張表來(lái)記錄同意過(guò)協(xié)議的用戶(hù)。表結(jié)構(gòu)大致是:id,客戶(hù)號(hào),插入時(shí)間。

詳細(xì)設(shè)計(jì)

1、記錄客戶(hù)是否已同意過(guò)協(xié)議并提供查詢(xún)功能(查詢(xún)是否同意過(guò)協(xié)議)

2、沒(méi)有同意過(guò)的和同意過(guò)的用戶(hù)信息怎么存儲(chǔ)

3、如何高效的查詢(xún)是否同意過(guò)

4、怎么保證高并發(fā)下服務(wù)的可用性,數(shù)據(jù)庫(kù)的可用性

功能實(shí)現(xiàn)

后端提供兩個(gè)接口,

1、hasAgree(),查詢(xún)?cè)撚脩?hù)是否已同意協(xié)議

2、recordAgree(),記錄用戶(hù)已同意協(xié)議

第一版 Just DB

很容易嘛!不就是CRUD嗎,小意思。用戶(hù)進(jìn)來(lái)先查數(shù)據(jù)庫(kù)有沒(méi)有記錄,沒(méi)有返回用戶(hù)沒(méi)有同意過(guò)協(xié)議,前端給用戶(hù)展示協(xié)議頁(yè),否則展示功能頁(yè);用戶(hù)點(diǎn)同意后,后臺(tái)記錄用戶(hù)已點(diǎn)了同意協(xié)議,記錄到庫(kù)。一個(gè)查詢(xún)一個(gè)插入,5分鐘搞定嘛。

直接甩代碼

第一版代碼如上,我覺(jué)得剛?cè)腴T(mén)的程序員都能夠?qū)懗鰜?lái)。如果用戶(hù)量不大,該功能的點(diǎn)擊量不大的話(huà),這么做還是勉強(qiáng)說(shuō)得過(guò)去。為什么說(shuō)勉強(qiáng)說(shuō)得過(guò)去,因?yàn)榇嬖陔[患,你看啊如果每次點(diǎn)擊都會(huì)去查庫(kù),假如有人惡意攻擊,仿造高并發(fā),瞬時(shí)大量請(qǐng)求過(guò)來(lái)都去查庫(kù),很可能數(shù)據(jù)庫(kù)頂不住就掛了?;蛘呔退銛?shù)據(jù)庫(kù)沒(méi)掛,每次查庫(kù)也都是浪費(fèi)啊。所以這是個(gè)隱患,或者潛在的危險(xiǎn),那么第二版我們就去解決這個(gè)問(wèn)題。

第二版 引入Redis緩存

考慮到每次查庫(kù)很浪費(fèi),那我們使用緩存好不好? 進(jìn)來(lái)先查緩存有沒(méi)有對(duì)應(yīng)的數(shù)據(jù),緩存里有就直接返回,沒(méi)有則查庫(kù),庫(kù)里有就存緩存。這樣redis就分擔(dān)了一部分?jǐn)?shù)據(jù)庫(kù)的壓力。

 

代碼呈上

這一版好一點(diǎn)了,部分請(qǐng)求分?jǐn)偟絩edis了,減輕了數(shù)據(jù)庫(kù)的壓力。

第三版 解決緩存穿透

隨著客戶(hù)量的增加,點(diǎn)擊這個(gè)功能的次數(shù)、頻率越來(lái)越高,假如有人頻繁點(diǎn)擊該功能,彈出協(xié)議后,退出,再點(diǎn),再退出…就是不點(diǎn)確定

 

這樣會(huì)有啥問(wèn)題?

這樣的話(huà)后臺(tái)緩存中沒(méi)有,數(shù)據(jù)庫(kù)中也沒(méi)有,每次都會(huì)走數(shù)據(jù)庫(kù),繞過(guò)了緩存,直接都走數(shù)據(jù)庫(kù),這類(lèi)請(qǐng)求量多了也是個(gè)問(wèn)題,這就是緩存穿透。所以第三版,我們來(lái)解決緩存穿透的問(wèn)題。

 

解決緩存穿透:因?yàn)槭菙?shù)據(jù)庫(kù)和緩存都沒(méi)有,我們可以讓數(shù)據(jù)庫(kù)沒(méi)有的也存到redis。需要改變r(jià)edis的數(shù)據(jù)類(lèi)型,由set改為map,目的是記錄狀態(tài)值。

可以看到,我們的這個(gè)key-field-value沒(méi)有設(shè)置過(guò)期時(shí)間,因?yàn)榭梢哉J(rèn)為這個(gè)key是一個(gè)熱點(diǎn)key,對(duì)于熱點(diǎn)key我們的處理方式是,永久有效或過(guò)期時(shí)間盡量長(zhǎng)一點(diǎn)。

第四版 緩存預(yù)熱防止緩存擊穿

另一個(gè)關(guān)于緩存的問(wèn)題,那就是緩存擊穿。

何為緩存擊穿?假如該功能在前期宣傳力度比較大,或預(yù)計(jì)該功能上線(xiàn)后點(diǎn)擊量比較大的話(huà),那么在功能上線(xiàn)后很可能就會(huì)一瞬間大量用戶(hù)來(lái)點(diǎn)擊這個(gè)功能,因?yàn)槲覀兦懊娴倪壿嬍鞘状芜M(jìn)入該功能的用戶(hù)展示協(xié)議頁(yè),我們的后臺(tái)處理雖然加了redis緩存,但是新上的功能所有用戶(hù)都沒(méi)有點(diǎn)過(guò),那么redis里就沒(méi)有緩存,是不是所有用戶(hù)的請(qǐng)求都落到數(shù)據(jù)庫(kù)了?一旦瞬間流量非常大,數(shù)據(jù)庫(kù)安全性就存在隱患,有被搞垮的可能。

 

這個(gè)問(wèn)題就是可以理解為緩存擊穿。(實(shí)際的緩存擊穿是某個(gè)key在緩存里不存在或是失效后,某一瞬間很多請(qǐng)求都來(lái)訪問(wèn)這個(gè)key,都判定為redis里沒(méi)有這個(gè)key,就都去查庫(kù)。)

所以怎么解決呢?我們可以在該功能上線(xiàn)前,提前將需要做緩存的數(shù)據(jù)放入redis,即緩存預(yù)熱。

如何預(yù)熱?將所有用戶(hù)的信息都放到redis.舉個(gè)栗子(也許不是最佳的),我們使用Redis的hash數(shù)據(jù)結(jié)構(gòu),key-field-value。key我們可以固定一個(gè)字符串如coderTreeHole_Agreement_Check,field我們可以用客戶(hù)號(hào)(唯一),value是個(gè)標(biāo)志位,用0代表沒(méi)同意過(guò)協(xié)議,1代表同意過(guò)。一般在電商大促前都會(huì)對(duì)熱點(diǎn)key進(jìn)行預(yù)熱,不然真的扛不住。

 

and,用戶(hù)量很大的時(shí)候redis里的coderTreeHole_Agreement_Check這個(gè)key是不是很大?在redis集群部署模式下,這個(gè)key是不是都放在一個(gè)節(jié)點(diǎn)上?why?

redis3.0上加入了cluster模式,實(shí)現(xiàn)的redis的分布式存儲(chǔ),也就是說(shuō)每臺(tái)redis節(jié)點(diǎn)上存儲(chǔ)不同的內(nèi)容。在redis的每一個(gè)節(jié)點(diǎn)上,都有這么兩個(gè)東西,一個(gè)是插槽(slot),它的的取值范圍是:0-16383。還有一個(gè)就是cluster,可以理解為是一個(gè)集群管理的插件。當(dāng)我們的存取的key到達(dá)的時(shí)候,redis會(huì)根據(jù)crc16的算法得出一個(gè)結(jié)果,然后把結(jié)果對(duì)16384求余數(shù),這樣每個(gè)key都會(huì)對(duì)應(yīng)一個(gè)編號(hào)在0-16383之間的哈希槽,通過(guò)這個(gè)值,去找到對(duì)應(yīng)的插槽所對(duì)應(yīng)的節(jié)點(diǎn),然后直接自動(dòng)跳轉(zhuǎn)到這個(gè)對(duì)應(yīng)的節(jié)點(diǎn)上進(jìn)行存取操作。

看了上面這段話(huà),明白了吧。那對(duì)于這個(gè)大key而且是熱點(diǎn)key的請(qǐng)求,是不是都落到某一個(gè)redis節(jié)點(diǎn)上了?大key會(huì)帶來(lái)很多問(wèn)題,篇幅原因以后再來(lái)細(xì)說(shuō),跑題了。。。

針對(duì)這個(gè)需求,你還有什么方法防治緩存擊穿?

第五版 消息隊(duì)列削峰填谷

可以看到我們上面的設(shè)計(jì)其實(shí)都是實(shí)時(shí)對(duì)數(shù)據(jù)庫(kù)進(jìn)行操作的。

例如,當(dāng)用戶(hù)點(diǎn)了同意,前端就調(diào)后臺(tái)的recordAgree方法將該記錄記錄到數(shù)據(jù)庫(kù),即這條記錄是立馬插入到數(shù)據(jù)庫(kù)的。

如果剛上線(xiàn)這個(gè)功能,大量用戶(hù)同時(shí)點(diǎn)這個(gè)功能,并發(fā)量大的話(huà),請(qǐng)求走到后臺(tái),那么寫(xiě)庫(kù)的操作就非常多,數(shù)據(jù)庫(kù)連接數(shù)突然激增,數(shù)據(jù)庫(kù)會(huì)頂不住吧。

所以為避免流量集中落到數(shù)據(jù)庫(kù),此時(shí)我們可以使用消息隊(duì)列MQ。將插入操作的請(qǐng)求發(fā)往消息隊(duì)列,使插入操作以一定的速率到數(shù)據(jù)庫(kù)執(zhí)行,使得對(duì)數(shù)據(jù)庫(kù)的請(qǐng)求數(shù)盡量平滑,消息發(fā)給消息隊(duì)列立即返回給前端成功,不用等待插庫(kù)完成,用MQ實(shí)現(xiàn)了異步解耦,削峰填谷。

到這你是不是忍不住說(shuō)設(shè)計(jì)的真贊~~

另外MQ的使用注意的點(diǎn)還是非常多的,如:消息隊(duì)列的消息重復(fù)消費(fèi)問(wèn)題,順序問(wèn)題,事務(wù)消息等。

總結(jié)

對(duì)于這個(gè)需求設(shè)計(jì)到哪種程度取決于你的用戶(hù)量和并發(fā)量,如果是像雙十一那樣,肯定是要用消息隊(duì)列的,那一般小的例如,用戶(hù)量1千萬(wàn),日活10萬(wàn),請(qǐng)求最集中的也就是中午9-12點(diǎn),下午13-17點(diǎn)吧,差不多8個(gè)小時(shí),平均一個(gè)小時(shí)1.25萬(wàn),用戶(hù)都來(lái)點(diǎn)這個(gè)功能的話(huà),每分鐘208,每秒3.5,算不上高并發(fā),數(shù)據(jù)庫(kù)完全扛得住。

總結(jié)一下,這個(gè)需求我們用到的知識(shí)點(diǎn)(敲黑板),redis數(shù)據(jù)緩存,redis緩存穿透,緩存擊穿,熱點(diǎn)key問(wèn)題,redis大key問(wèn)題(沒(méi)具體講),消息隊(duì)列異步解耦等。

畫(huà)圖碼字不易,如果覺(jué)得我寫(xiě)的還可以,記得點(diǎn)贊鼓勵(lì)一下哦,如果覺(jué)得有問(wèn)題歡迎指正。

好了,就給大家介紹這么多。

您可能感興趣的文章:
  • CentOS系統(tǒng)下Redis安裝和自啟動(dòng)配置的步驟
  • Python使用Redis實(shí)現(xiàn)作業(yè)調(diào)度系統(tǒng)(超簡(jiǎn)單)
  • Nginx配置srcache_nginx模塊搭配Redis建立緩存系統(tǒng)
  • CentOS Linux系統(tǒng)下安裝Redis過(guò)程和配置參數(shù)說(shuō)明
  • 讓Redis在你的系統(tǒng)中發(fā)揮更大作用的幾點(diǎn)建議

標(biāo)簽:仙桃 崇左 湘潭 銅川 黃山 蘭州 衡水 湖南

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《從一個(gè)小需求感受Redis的獨(dú)特魅力(需求設(shè)計(jì))》,本文關(guān)鍵詞  ;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問(wèn)題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無(wú)關(guān)。
  • 相關(guān)文章
  • 收縮
    • 微信客服
    • 微信二維碼
    • 電話(huà)咨詢(xún)

    • 400-1100-266