緩存服務(wù)器有哪些端緩存(緩存服務(wù)器有哪些作用)     DATE: 2026-05-05 07:01:18

人生??不過(guò)如此,緩存且行且珍惜。服務(wù)自己永遠是端緩自己的主角,不要總在別人的存緩存服戲劇里充當著(zhù)配角。

我以林語(yǔ)堂的有作用《人生不過(guò)如此》中一句話(huà)來(lái)開(kāi)篇。

背景

在互聯(lián)網(wǎng)高速發(fā)展、緩存快速演化的服務(wù)時(shí)代,想必在你的端緩系統架構設計中,緩存服務(wù)是存緩存服不是已經(jīng)成為必不可少的一層,豐富的有作用數據結構、高性能的緩存讀寫(xiě)、簡(jiǎn)單的服務(wù)協(xié)議,讓緩存數據庫很好的端緩承擔起關(guān)系型數據庫的上層。暢途網(wǎng)為了(′?`*)解決節假日或高峰期的存緩存??服車(chē)次查詢(xún)、搶票等大數據量的有作用訪(fǎng)問(wèn)請求,很早以前就引進(jìn)了 Redis,來(lái)作為數據庫的上游緩存層,緩解底層數據庫的讀寫(xiě)壓力。

REDIS HA 架構

世界上唯一可以不勞而獲的就是貧窮,唯一可以無(wú)中生有的是夢(mèng)想。沒(méi)有哪件事,不動(dòng)手就可以實(shí)現。世界雖然殘酷,但只(zhi)要(?????)你愿意走,總會(huì )有路;看不到美好,是因為你沒(méi)有堅持走下去。人(′?`)生貴在行動(dòng),遲疑不決時(shí),不妨先邁出小小一步。(╯°□°)╯前進(jìn)不必遺憾,若是美好,叫做精彩;若是糟糕,叫做經(jīng)歷。(′ω`*)**——林語(yǔ)堂《人生不過(guò)如此》

2014 年 10 月,為了避免單點(diǎn)故障,我們嘗試在生產(chǎn)環(huán)境的 Redis 主從架構中,引入了 Redis Sentinel,實(shí)現了 Redis 服務(wù)的 failover。當 Redis-Master 主機異常宕機或 Redis-Master 服務(wù)異常崩潰時(shí),原有的 Redis-Slave 自動(dòng)升級為 master 角色,當原有 Redis-Master 恢復后,自動(dòng)恢復為 slave 角色(′▽?zhuān)?。

由于 Redi??s Sentinel 只能做到 Redis 服務(wù)級別的切換,無(wú)法做到 IP 地址的切換,無(wú)法完全滿(mǎn)??足現網(wǎng)系統架構的需要,我們又嘗試在 HA 架構中加入了(°□°)負載均衡器設備,引用了浮動(dòng) IP,所有應用程序訪(fǎng)問(wèn)浮動(dòng) IP,IP 地址的切換操作(°ロ°) !由負載均衡器設備來(lái)實(shí)現。

Redis Sentinel 配置文件

測試小結:

主 Redis 服務(wù)器:redis-sent-0-17

從 Redis 服務(wù)器:??redis-sent-0-18

域名:

redis-sent.cache.changtu.p??vt

對應用程序的要求

2015 年新增 2 臺 Redis Senヾ(′ω`)?tinel 服務(wù)器,負責平臺所??有 Redis 服務(wù)器集群管理。并對平臺現有 Redis 服務(wù)進(jìn)行改造??,逐步升級為 Redis HA 架構。

CODIS 分布式集群

你可以一輩子不登山,但你心中一定要有座山。它使你總往高處爬,它使你總有個(gè)奮斗的方(fang)向,它使你任何一刻抬起頭,都能看??到自(zi)己的希望?!终Z(yǔ)堂《人生不過(guò)(guo)如此》

隨著(zhù)暢途網(wǎng)業(yè)務(wù)量上漲,數據量猛增,單點(diǎn)的 Redis 容量受限于服務(wù)器的內存,Rediヽ(′▽?zhuān)?ノs 主從??架構已經(jīng)力不從心??了。在業(yè)務(wù)系統對性能要求逐漸提高情況下,我們更希望將數據能存在內存中,本地持久化,而不希望寫(xiě)入數據庫中。雖然當時(shí)用 SSD 將內存換成磁盤(pán),以獲取更大的容量,但是我們更想如何將 redis 變成一個(gè)可以水平擴展的分布式緩存服務(wù)?

在 Codis 發(fā)布之前,業(yè)界只有 Twemproxy,??Twemproxy 本身是(shi)一個(gè)靜態(tài)的分布式 Redis 方案,進(jìn)行擴容、縮容對運維要求非常高,而且很難做到平滑的擴縮容。Codis 的目標就是盡量兼容 Twe(′?ω?`)mproxy,并且加上數據遷移的功能以實(shí)現(xian)擴容和縮容,最終替換 Twemproxy。本文省略了對 Twemproxy 的介紹。

REDIS-CLUSTER

與 Codis 同時(shí)期發(fā)布的官方 redis-cluster,采用 P2P 的模式,完全去中心化架??構, 其實(shí)我們花了大精力研究測試過(guò),由于當時(shí)對 failover 判斷方式提出懷疑,高耦合的模塊設計思想、(′_`)客戶(hù)端問(wèn)題、不太??友??好的維護等(deng)方面, 我司目前沒(méi)有投入生產(chǎn),沒(méi)有了(le)實(shí)際的生產(chǎn)維護經(jīng)驗,我先不發(fā)表看法。抱拳,我知道在緩存數據庫里最不應該缺少的就是 Redis-cluster 了,以后有機會(huì )單獨介紹吧!

容我感嘆一下,別指望所有的人都能懂你,因為蘿卜白菜,各有所愛(ài)。你做了蘿卜,自然就做不成青菜。

好了,回歸正題,先簡(jiǎn)單介紹一下 Codis,由豌豆莢于 2014 年 11 月開(kāi)源,基于 Go 和 C 開(kāi)發(fā),??引用作者的一段原話(huà), Codis 采用一層無(wú)狀態(tài)的 proxy 層,將分布式邏輯寫(xiě)在 proxy 上,底層的存儲引擎是 Redi??s,數據的分布狀態(tài)存儲于 zookeeper(etcd) 中,底層的數據存儲變成了可插拔的部件。各個(gè)部件是可以動(dòng)態(tài)水平擴展的,尤其無(wú)狀態(tài)的 proxy 對于動(dòng)態(tài)的負載均衡,對業(yè)務(wù)而言完全是(′?`*)透明的。

*

核心組件說(shuō)明

1. ZooKeeper:

用來(lái)存放(′?`*)數據路由表和 Codis-proxy 節點(diǎn)的元信息,Codis-config 發(fā)起的命令都(dou)會(huì )通過(guò) ZooKeeper 同步到各個(gè)存活的 Codis??-proxy 中。

2. Codis-Proxy :

是客戶(hù)端連接的 Redis 代理服務(wù),本身是??沒(méi)狀態(tài)的,Codis-proxy 實(shí)現了 Redis 協(xié)議,對于一個(gè)業(yè)務(wù)來(lái)說(shuō),可以部署多個(gè) Codis-proxy, 提供??連(lian)接集群 Redis 服務(wù)的入(ru)口。

3. Codis-Config :

是 Cod???is 的集成管理工具,支持添加 / 刪除 Redis 節點(diǎn)、添加 / 刪除 Proxy 節點(diǎn)、以及發(fā)起數據遷移等(deng)操作,Codis-config 還自帶了 http server,會(huì )??啟動(dòng) dashboard,用戶(hù)可以在 WEB 上監控 Codis 集群的狀態(tài)。

4. Codis┐(′ー`)┌-ヽ(′▽?zhuān)?/Server:

是 Codiヽ(′▽?zhuān)?ノs 項目維護的一個(gè)(′?_?`) Redis 分支,基于 redis??-2.8.21 分支開(kāi)發(fā),增加了額外的數據結??構,以支持 slot 有關(guān)的操作以及數據遷移指令。

5.??Pre-Sharding 技術(shù)

Codis 采用 Pre-Shardi??ng 的技術(shù)來(lái)實(shí)現數據的分片, 默認分成 1024 個(gè) slots (0-1023), 對于每個(gè) key 來(lái)說(shuō),(′▽?zhuān)?) 通過(guò)以下公式確定所屬的 Slot Id : SlotId = crc32(key) % 1024,每一個(gè) slot 都會(huì )有一個(gè)特定的 server(⊙_⊙) group id 來(lái)表??(biao)示這個(gè) slot 的數據由哪個(gè) server gr??oup 來(lái)提供。

在 2016 年 6 月左右,我們引進(jìn)了 Codis(當時(shí)版本是 3.0,并沒(méi)有 Redis-Sentinel、Codis-fe 等組件,1 年后,才升級到 3.??2 的,文章主要以 3.0 版本為背景),首先介紹一下基礎環(huán)境。

系統架構

在公司硬件資源有限條件下,我們計劃用 6 臺服務(wù)器部署 Codis,簡(jiǎn)單分了兩層,Codis-Proxy 層和 Codis-Server 層。

我們分別通過(guò) jredis 編寫(xiě)測試程序和使用 redis-benchmark 工具模擬壓力測試(請求量:1000 萬(wàn)~1 億,并發(fā)(fa)數:1000~50000,長(cháng)度??:固定 / 可變):

倔強的青銅

于是組織研??發(fā)同事進(jìn)行多次分析討論,并提?出了對??緩存服務(wù)進(jìn)行接口改造,經(jīng)過(guò) 2 個(gè)多月的辛勞,取得了很大進(jìn)展,讓我們 Codis 項目順利上線(xiàn)邁開(kāi)了重要一步,打??斷一下,容我在此特別感謝一下同事王慧,在他的主導下,完成公司???絕大部分緩存服務(wù)接口改造工作。

幾點(diǎn)改造思路

1. 緩存服務(wù)分類(lèi)。

2. 對緩存服務(wù)進(jìn)行接口改造,新增基礎緩存服務(wù)層,將生產(chǎn)的 Re(′_ゝ`)dis/Codis 相關(guān)的服務(wù)納入基礎緩存服務(wù)進(jìn)行統一管理。

3.SLOT 的分配

哈希算法(fa)

Codis 采用 Pre-sharding 的技術(shù)來(lái)實(shí)現數據的分片, 默認分成 1024 個(gè) slots (0-1023), 對于每個(gè) key 來(lái)說(shuō), 通過(guò)以下公式確定所屬的 Slot Id : SlotId = crc32(key) % 1024。例如 pub┐(′?`)┌_cty_ct018 根據算法得???出的值是 997。

key 值重定向分配

比如你有一個(gè)腳本是操作某個(gè)用戶(hù)的多個(gè)信息,如 uid1age,uid1sex,uid1??name 形如此類(lèi)的 key,如果??你不用 hashtag 的話(huà),這些 key 可能會(huì )分(?_?;)散在不同的機器上,如果使用了 hashtag(用花括號擴住計算 hash 的區域):{ uid1}age,{ uid1}sex,{ uid1}name,這樣就保證這些 key 分布在同一個(gè)機器上。這個(gè)是 twemproxy 引入的一個(gè)語(yǔ)法,我們這邊也支持了。

以 pub_cty 為例,通過(guò) crc32hash 算法得出,key 存放在 237 slot 中(zhong),類(lèi)似測試了{ pub_cty}_ct01,{ pub_cty}_ct02…{ pub_cty}_ctnn 都存放在 237 slot 中。第一,有了 hashtag 算法支持,我們可以對特定需求的 key 做一些特需的規劃,將這些特殊的 key 有序的存放在 codis slot 中,保證 mget/mset, 以及 lua 腳本正常執行。我們目前大概管理 200 多個(gè) redis 鍵,統一鎖定到一個(gè) codis-server(slot)中。第二,在某些極端情況(不希望發(fā)生(sheng)),如某 codis-group 中的 master 異?;虮罎r(shí),我們從程序設計角度,盡可能對出現的無(wú)法(′▽?zhuān)?進(jìn)行操作?? KEY 的行為做一些 " 某種意義上 " 保護。譬如,當某 codis-??group 的 maser(╬?益?) 宕機(???)時(shí),對 codis?? 進(jìn)行寫(xiě)操作,如果對應的 key 落到宕機的主機上,會(huì )得到異?;蛘??錯誤,可以通過(guò)捕獲異常信息,將異常的 key 通過(guò)改變 key 名的規則將其存放到其他 codis-group 上。同理(′ω`),如果是讀取宕機主機上的 key 數據時(shí)??,將其引導到調整后的 key 上,在一定程度上保障 codis 的完整性(不保障數據不丟失,只保證業(yè)務(wù)系統操作緩存數據完整性)。

有點(diǎn)意思的整改

在長(cháng)(?????)達幾年的迭代演變過(guò)程中,??維護團隊推動(dòng)多次緩存服務(wù)架構的升級與優(yōu)化,緩存服務(wù)逐漸完善和穩定。 記下了一些“有點(diǎn)意思”的(′?`*)整改,提供大家參(?_?;)考。

熱點(diǎn)數據

統計緩存熱點(diǎn)數據,在基礎緩存服務(wù)層上假設二級緩存,作為熱點(diǎn)數據的快速通道,具備可動(dòng)態(tài)獲取,最快訪(fǎng)問(wèn),少變化的特點(diǎn) 。

根據緩存服務(wù)各主、子鍵關(guān)系,使用 index_{ 主鍵}的方式來(lái)作為管理主子鍵關(guān)系的 SortedSet 集合,統計數據的使(O_O)用頻率,抽取 Top100 的數??據,作為熱點(diǎn)數據。對這批數據進(jìn)行分析,結合數據的改動(dòng)頻率,制定這批數據??緩存在內存中的時(shí)長(cháng)。

二級緩存設計

緩存數據列表生成與維護

內存緩存數據的?? key 列表由緩存服務(wù)生成和維護,Key 列表包括后臺手動(dòng)配置(如,10 個(gè))和系統根據使??用熱度生成(如,20 個(gè))共同組成,其中 cache-manager 的 jar 包只負責對該數據使用,通過(guò)定時(shí)任務(wù)獲取 codis 中的前 20 位和(he)后臺手動(dòng)配置的相關(guān)數據,期間要保證獲取(qu)到數據的有效性。

維護本地內存中的數據

自然統計內存緩存:用?? sortedSet 集(ji)合,統計各主鍵下的所有鍵 Get 的次數??,匯總(′▽?zhuān)?成 score_{ 主鍵}方式的集合。利用 ZIncrby 命令統計對應的子鍵的次數,最終匯總每個(gè)主鍵,統計出 Top10??0 的 key,利用 zunionstore 命令將信息統計匯總作為內存緩存(cun)的基礎,此集合內數據均從內(nei)存中獲取。

在發(fā)生??手動(dòng)更新時(shí),對內存中對應的主鍵進(jìn)行更新

在發(fā)生更新時(shí),由(you)后臺發(fā)起,在(zai)緩存服務(wù)向 codis 中置入標志(zhi)位,各客戶(hù)端在定時(shí)任(ren)務(wù)中獲取標志位,如果標志位(cache_memory_update_flag)為 Y,則清空內存和 Key 規則表,等到下一個(gè)更新周期來(lái)臨重新獲取數據。

總結??

多年后,再回想年少時(shí)的迷茫和執著(zhù),或許原因都記不得了。青春就是讓(????)你張揚的笑,也給你莫名??的痛?!终Z(yǔ)堂《人生不過(guò)如此》

經(jīng)過(guò)大??半年的時(shí)間測ˉ\_(ツ)_/ˉ試、緩存服務(wù)接口改造,在 20??16 年 9 月份,趕在國慶前,我們的 Codis3.0 上線(xiàn)了,在車(chē)次查詢(xún)等方面,有了質(zhì)的飛越,尤其節假日或高峰期(qi)期間,平滑的擴縮容、數據遷移、高可用等方面展示出巨大優(yōu)勢。

三個(gè) codis_proxy 節點(diǎn)的均衡情況:

1 年后,2018 年 8~9 月份,我們將 Codis 升級到 3.2 的,由之前 6 臺服務(wù)器,擴展到 7 臺,實(shí)際上多一臺 Codis-web 節點(diǎn),獨立承擔 Codis-fe、Codis-dashboard 等組件。對于 Redis-Sent??inel、Codis-fe 等組件的引進(jìn),解決了運維人員很??多問(wèn)題,在ヾ(′▽?zhuān)??此不再描述,有興趣的可以參考。

https://githu???b.com/CodisLabs/codis/blob/3.2.2/doc/tutorial_zh.md

目前 Codis 作為暢途網(wǎng)最為核心ヽ(′ー`)ノ的緩存層,一如既往的穩定輸出,肩負起它的神圣使命!

版權聲明:本文內容由互聯(lián)網(wǎng)用戶(hù)自發(fā)貢獻,該ヾ(′▽?zhuān)??文觀(guān)點(diǎn)僅代表作者本人。本站僅提供信息存儲空間服務(wù),不擁有所有權,不承擔相關(guān)法律責任。如發(fā)現本站有涉嫌抄襲侵權/(′?_?`)違法違規的內容, 請發(fā)送郵件至 [email protected]??m 舉報(′▽?zhuān)?,一經(jīng)查實(shí),本站將立刻刪除。