自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Redis 是什么?架構(gòu)是怎么樣的?

數(shù)據(jù)庫(kù) Redis
有沒(méi)有辦法在 MySQL 不被壓垮的同時(shí),讓商品服務(wù)支持每秒 1w 次查詢 ?當(dāng)然有,沒(méi)有什么是加一層中間層不能解決的,如果有,那就再加一層。這次我們要加的中間層是Redis。

你是一個(gè)程序員,你維護(hù)了一個(gè) 商品服務(wù),它背后直連 mysql 數(shù)據(jù)庫(kù)。
假設(shè)商品服務(wù)需要對(duì)外提供 每秒 1w 次查詢,但背后的 mysql 卻只能提供每秒 5k 次查詢,那 mysql 根本頂不??!分分鐘會(huì)被壓垮。

這類大流量查詢場(chǎng)景非常常見(jiàn),比如雙十一秒殺和春節(jié)搶車票。
那么問(wèn)題就來(lái)了,有沒(méi)有辦法在 mysql 不被壓垮的同時(shí),讓商品服務(wù)支持每秒 1w 次查詢 ?
當(dāng)然有,沒(méi)有什么是加一層中間層不能解決的,如果有,那就再加一層。
這次我們要加的中間層是Redis。

本地緩存

我們知道,查詢內(nèi)存的速度比查詢磁盤要快, mysql 數(shù)據(jù)主要存放在磁盤里,如果能將 mysql 里的數(shù)據(jù)放內(nèi)存里,查詢完全不走磁盤,那必然能大大提升查詢性能。

我們很容易想到,可以在商品服務(wù)的內(nèi)存中,申請(qǐng)一個(gè)字典,在 python 里叫 dict,在 java 里叫 map。

key 是商品 ID,value 是商品數(shù)據(jù)。通過(guò)商品 ID, 就能查到商品數(shù)據(jù)。

發(fā)生查詢時(shí),優(yōu)先去查內(nèi)存字典,沒(méi)結(jié)果再跑到 mysql 數(shù)據(jù)庫(kù)里查詢,再將結(jié)果順手放內(nèi)存字典里,下次就又能從內(nèi)存里查出來(lái)啦。

像這樣,放在服務(wù)內(nèi)部的緩存,就是所謂的本地緩存。
有了本地緩存的加持,真正打到 mysql 的查詢量就跟你喜歡的女生回你的消息字?jǐn)?shù)一樣少,將查詢請(qǐng)求干到 1w qps 是很輕松的事情。

遠(yuǎn)程緩存

但問(wèn)題又來(lái)了,為了保證系統(tǒng)高可用,商品服務(wù)經(jīng)常不止一個(gè)實(shí)例,如果每個(gè)實(shí)例都重復(fù)緩存一份本地內(nèi)存,那就有些浪費(fèi)內(nèi)存條了。
所以更好的解決方案是將這部分字典內(nèi)存抽出來(lái),單獨(dú)做成一個(gè)服務(wù)。它就是所謂的遠(yuǎn)程緩存服務(wù)。

但這就引入另外一個(gè)問(wèn)題,多個(gè)商品服務(wù)通過(guò)網(wǎng)絡(luò)去讀寫同一份遠(yuǎn)程緩存,會(huì)存在并發(fā)問(wèn)題。怎么辦呢?
很簡(jiǎn)單!對(duì)外不管有多少有個(gè)網(wǎng)絡(luò)連接,收到讀寫命令后,都統(tǒng)一塞到一個(gè)線程上,在一個(gè)線程上對(duì)字典進(jìn)行讀寫,什么并發(fā)問(wèn)題和線程切換開(kāi)銷,完全不存在!

這個(gè)遠(yuǎn)程緩存服務(wù)足以滿足大部分場(chǎng)景,但它屬實(shí)過(guò)于簡(jiǎn)陋,我們來(lái)看下怎么優(yōu)化它。

多種數(shù)據(jù)類型支持

現(xiàn)在緩存服務(wù)里,只有一個(gè)字典類型。key 和 value 都是字符串。但我們平時(shí)寫代碼的時(shí)候,還會(huì)用到很多其他內(nèi)存里的數(shù)據(jù)結(jié)構(gòu),是不是也可以在緩存服務(wù)里提供類似的數(shù)據(jù)結(jié)構(gòu)?
于是我們對(duì)字段的 value 進(jìn)行擴(kuò)展,除了 字符串, 還支持先進(jìn)先出的隊(duì)列 List 和用于去重的 Set 類型,再加入可以做排行榜的 ZSet,現(xiàn)在緩存服務(wù)就更強(qiáng)了。

內(nèi)存過(guò)期策略

緩存服務(wù)支持的數(shù)據(jù)結(jié)構(gòu)變多了之后,塞到內(nèi)存里的數(shù)據(jù)就越來(lái)越多了,內(nèi)存又小又貴,遲早扛不住。
怎么辦呢?我們可以給緩存里的數(shù)據(jù)加個(gè)過(guò)期時(shí)間,一旦數(shù)據(jù)過(guò)期,就從內(nèi)存里刪掉,可以很大程度緩解掉內(nèi)存增長(zhǎng)速度。
但問(wèn)題又又來(lái)了,我怎么知道哪些數(shù)據(jù)該設(shè)置多長(zhǎng)過(guò)期時(shí)間呢?
完全沒(méi)辦法,只能交給調(diào)用方去做判斷,讓用戶通過(guò) expire 命令的形式來(lái)指定哪些數(shù)據(jù)多久過(guò)期。

緩存淘汰

但你不能指望每個(gè)調(diào)用方都是老實(shí)人,如果都不設(shè)置過(guò)期時(shí)間,那內(nèi)存還是得炸。
有解法嗎?
有!在內(nèi)存接近上限的時(shí)候,根據(jù)一些策略刪除掉一些內(nèi)存。比如可以將最近最少使用的內(nèi)存刪掉,也就是所謂的 LRU,這樣不僅解決了內(nèi)存過(guò)大的問(wèn)題,還讓 redis 里的數(shù)據(jù)全是熱點(diǎn)數(shù)據(jù)。真是一箭雙雕。

持久化

現(xiàn)在內(nèi)存過(guò)大的問(wèn)題是解決了。但還有個(gè)問(wèn)題,mysql 之所以過(guò)得那么舒服,那是因?yàn)榍懊嬗袀€(gè)緩存服務(wù)擋住了大部分流量。一旦緩存服務(wù)重啟,那內(nèi)存就全丟了,這時(shí)候流量會(huì)全都打到 mysql 身上,疼得它嗷嗷叫。

所以我們還需要給 redis 加入最大程度的持久化保證。確保服務(wù)重啟后不至于什么數(shù)據(jù)都沒(méi)有。
于是可以在緩存服務(wù)里加個(gè)異步線程,定期將全量?jī)?nèi)存數(shù)據(jù)定期持久化到磁盤文件里,而這種將內(nèi)存數(shù)據(jù)生成快照保存到文件的方式,就是所謂的 RDB,Redis Database Backup。

它可以每隔幾分鐘記錄下緩存服務(wù) 的全量數(shù)據(jù),類似于游戲的"存檔"。
這樣就算進(jìn)程掛了,重啟的時(shí)候,通過(guò)加載快照文件,就能復(fù)原大部分?jǐn)?shù)據(jù)。
之所以說(shuō)是大部分,是因?yàn)?存檔"之后寫入的數(shù)據(jù)可能會(huì)丟。
那還有其他方式可以保留更多數(shù)據(jù)嗎?有!
全量數(shù)據(jù)備份當(dāng)然耗時(shí),那我們化整為零,在每次寫入數(shù)據(jù)時(shí),順手將數(shù)據(jù)記錄到文件緩存中,并每秒將文件緩存刷入磁盤,這種持久化機(jī)制叫 AOF,Append Only File,服務(wù)啟動(dòng)時(shí)跟著文件重新執(zhí)行一遍就能將大部分?jǐn)?shù)據(jù)還原,最大程度保證了數(shù)據(jù)持久化。

那問(wèn)題就來(lái)了,AOF 文件會(huì)不會(huì)很大?沒(méi)事,定期重寫壓縮就行,比如 a 被依次賦值 a=1,a=2,最終保留 a=2 就夠了。

簡(jiǎn)化網(wǎng)絡(luò)協(xié)議

剛剛提到遠(yuǎn)程緩存服務(wù)對(duì)外提供讀寫能力,那是對(duì)外提供的 HTTP 接口嗎?
當(dāng)然不是!
我們知道, HTTP 是基于 TCP 做的通信,實(shí)現(xiàn)了很多笨重的特性。
既然當(dāng)初是為了性能,特地上的緩存服務(wù),那就索性徹底點(diǎn),拋棄 HTTP,直接基于 TCP 做傳輸就好!傳輸協(xié)議也設(shè)計(jì)得簡(jiǎn)單點(diǎn),比如只要通過(guò) TCP 傳入 SET key value,就能完成寫入。傳入"GET key" 就能獲得對(duì)應(yīng)的 value。非常簡(jiǎn)潔。
那傳輸協(xié)議的解析需要我們自己寫代碼去實(shí)現(xiàn)嗎?
完全不需要,redis 官方提供了一個(gè)命令行工具,redis-cli,通過(guò)它,我們可以輸入一些命令,讀寫 Redis 服務(wù)器里的各種內(nèi)存數(shù)據(jù)。

不想用命令行也沒(méi)關(guān)系,各路大神已經(jīng)用各種語(yǔ)言將 redis-cli 支持的命令實(shí)現(xiàn)了一遍,完全不需要自己手寫。

Redis 是什么?

好了,到這里,當(dāng)初那個(gè)簡(jiǎn)陋的遠(yuǎn)程緩存服務(wù),就成了一個(gè)高性能,支持多種數(shù)據(jù)類型和各種緩存淘汰策略,并提供一定持久化能力的超強(qiáng)緩存服務(wù),沒(méi)錯(cuò),它就是我們常說(shuō)的 Redis,全稱 Remote Dictionary Server,這名字就很精辟了,說(shuō)白了 redis 就是個(gè)遠(yuǎn)程的字典服務(wù)。

redis 作為架構(gòu)中最常用的提速神器,是萬(wàn)金油一般的存在,將它放在 mysql 面前擋一道查詢只是最基礎(chǔ)的用法。
通過(guò)擴(kuò)展插件,還能實(shí)現(xiàn)各種高階玩法。
比如 RedisJSON 支持復(fù)雜的 JSON 查詢和更新,說(shuō)白了就是內(nèi)存版本的 MongoDB。
RediSearch 支持全文搜索,說(shuō)白了就是內(nèi)存丐版的 es。
RedisGraph 支持圖數(shù)據(jù)庫(kù)功能,類似 Neo4j,RedisTimeSeries 處理時(shí)間序列數(shù)據(jù),也就是內(nèi)存版 InfluxDB。大有一種要在內(nèi)存里將所有中間件都實(shí)現(xiàn)一遍的味道。

現(xiàn)在大家通了嗎?

總結(jié)

  • redis 本質(zhì)上就是個(gè)遠(yuǎn)程字典服務(wù),所有讀寫命令等核心邏輯,都在一個(gè)線程上完成。什么并發(fā)問(wèn)題和線程切換開(kāi)銷,完全不存在!
  • redis 支持多種數(shù)據(jù)類型、內(nèi)存過(guò)期策略和多種緩存失效策略,通過(guò) TCP 對(duì)外提供了一套非常簡(jiǎn)單的傳輸協(xié)議。
  • redis 加入了最大程度的持久化保證。將數(shù)據(jù)持久化為 rdb 和 AOF,確保服務(wù)重啟后不至于什么數(shù)據(jù)都沒(méi)有。
  • redis 支持多種擴(kuò)展,玩法非常多,比如 RediSearch 和 RedisJSON。
責(zé)任編輯:姜華 來(lái)源: 小白debug
相關(guān)推薦

2025-01-20 07:00:00

2024-12-16 08:20:00

2025-02-03 08:00:00

HDFS架構(gòu)存儲(chǔ)數(shù)據(jù)

2024-06-24 00:07:00

開(kāi)源es搜索引擎

2024-03-04 08:03:50

k8sClusterNode

2024-05-22 08:02:30

2022-08-12 17:14:46

元宇宙

2009-12-24 14:05:06

Fedora core

2023-05-15 10:17:03

2017-10-17 15:02:35

RS-485總線布線雙絞線

2014-08-25 10:11:18

極致用戶體驗(yàn)

2020-08-13 12:02:13

前端培訓(xùn)學(xué)習(xí)

2014-02-18 11:24:07

云計(jì)算PaaS

2019-01-11 10:39:24

軟件架構(gòu)虛擬空間機(jī)器人

2011-05-31 17:27:58

網(wǎng)站權(quán)重

2016-03-09 11:25:39

前端開(kāi)發(fā)工程師簡(jiǎn)歷

2024-01-03 13:06:50

2018-06-21 08:38:05

編程語(yǔ)言程序員代碼

2024-04-24 07:00:00

Redis架構(gòu)數(shù)據(jù)持久化
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)