中文字幕在线观看,亚洲а∨天堂久久精品9966,亚洲成a人片在线观看你懂的,亚洲av成人片无码网站,亚洲国产精品无码久久久五月天

這些年,我們一起追過的緩存數(shù)據(jù)庫

2020-04-28    來源:raincent

容器云強勢上線!快速搭建集群,上萬Linux鏡像隨意使用

李曉峰

人生不過如此,且行且珍惜。自己永遠是自己的主角,不要總在別人的戲劇里充當著配角。

我以林語堂的《人生不過如此》中一句話來開篇。

背景

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

REDIS HA 架構(gòu)

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

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

由于 Redis Sentinel 只能做到 Redis 服務級別的切換,無法做到 IP 地址的切換,無法完全滿足現(xiàn)網(wǎng)系統(tǒng)架構(gòu)的需要,我們又嘗試在 HA 架構(gòu)中加入了負載均衡器設備,引用了浮動 IP,所有應用程序訪問浮動 IP,IP 地址的切換操作由負載均衡器設備來實現(xiàn)。

 

 

Redis Sentinel 配置文件

vi /appl/redis/etc/sentinel.conf
# Redis-ha redis-sent-0-17 redis-sent-0-18
port 26379
dir /appl/redis/database
logfile /appl/redis/log/sentinel.log
sentinel monitor redis-sent-0-17 172.19.0.17 6379 3
sentinel down-after-milliseconds redis-sent-0-17 20000
sentinel failover-timeout redis-sent-0-17 60000
sentinel can-failover redis-sent-0-17 yes
sentinel parallel-syncs redis-sent-0-17 1

測試小結(jié):

主 Redis 服務器:redis-sent-0-17

從 Redis 服務器:redis-sent-0-18

域名:redis-sent.cache.changtu.pvt

重啟 redis-sent-0-17 節(jié)點,60 秒后,redis-sent-0-18 節(jié)點成為 master,用戶訪問 redis-sent.cache.changtu.pvt 域名 redis 服務恢復正常,2 分鐘后,redis-sent-0-17 節(jié)點重啟完成,自動成為 slave;

重啟 redis-sent-0-18 節(jié)點,60 秒后,redis-sent-0-17 節(jié)點成為 master,用戶訪問 redis-sent.cache.changtu.pvt 域名 redis 服務恢復正常,2 分鐘后,redis-sent-0-18 節(jié)點重啟完成,自動成為 slave。

對應用程序的要求

緩存應用服務統(tǒng)一通過域名訪問。

緩存應用服務對 Redis 域名的訪問有斷點重連的功能。

2015 年新增 2 臺 Redis Sentinel 服務器,負責平臺所有 Redis 服務器集群管理。并對平臺現(xiàn)有 Redis 服務進行改造,逐步升級為 Redis HA 架構(gòu)。

CODIS 分布式集群

你可以一輩子不登山,但你心中一定要有座山。它使你總往高處爬,它使你總有個奮斗的方向,它使你任何一刻抬起頭,都能看到自己的希望。——林語堂《人生不過如此》

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

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

REDIS-CLUSTER

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

 

 

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

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

 

 

核心組件說明

1. ZooKeeper:

用來存放數(shù)據(jù)路由表和 Codis-proxy 節(jié)點的元信息,Codis-config 發(fā)起的命令都會通過 ZooKeeper 同步到各個存活的 Codis-proxy 中。

2. Codis-Proxy :

是客戶端連接的 Redis 代理服務,本身是沒狀態(tài)的,Codis-proxy 實現(xiàn)了 Redis 協(xié)議,對于一個業(yè)務來說,可以部署多個 Codis-proxy, 提供連接集群 Redis 服務的入口。

3. Codis-Config :

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

4. Codis-Server:

是 Codis 項目維護的一個 Redis 分支,基于 redis-2.8.21 分支開發(fā),增加了額外的數(shù)據(jù)結(jié)構(gòu),以支持 slot 有關(guān)的操作以及數(shù)據(jù)遷移指令。

5.Pre-Sharding 技術(shù)

Codis 采用 Pre-Sharding 的技術(shù)來實現(xiàn)數(shù)據(jù)的分片, 默認分成 1024 個 slots (0-1023), 對于每個 key 來說, 通過以下公式確定所屬的 Slot Id : SlotId = crc32(key) % 1024,每一個 slot 都會有一個特定的 server group id 來表示這個 slot 的數(shù)據(jù)由哪個 server group 來提供。

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

192.168.0.** codis-server1
192.168.0.** codis-server2
192.168.0.** codis-server3

192.168.0.** codis-ha1 (zookeeper-3)
192.168.0.** codis-ha2 (zookeeper-2)
192.168.0.** codis-ha3 (zookeeper-1)

系統(tǒng)架構(gòu)

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

Codis-Proxy 層用了三臺配置相對較低服務器,部署了 ZooKeeper、Codis-Proxy、Keepalived、LVS 等 ,3 個節(jié)點都做了負載均衡。

Codis-Server 層用來三臺配置相對較高的服務器,并用 SSD,3 個 Codis-group,每個 group 有一主一從,交叉部署,每個主從分配 30G 內(nèi)存。

maxclients 30000
maxmemory 30gb

 

 

 

我們分別通過 jredis 編寫測試程序和使用 redis-benchmark 工具模擬壓力測試(請求量:1000 萬~1 億,并發(fā)數(shù):1000~50000,長度:固定 / 可變):

在性能方面:基本上能達到我們的預期,理想情況 Codis 性能值能達到 50~60K OP/S,各個 codis-group 中 master-slave 實例數(shù)據(jù)能實時同步,詳情可以參考《Codis 高可用集群性能測試報告 _20160315》。

數(shù)據(jù)一致性問題:一方面,Codis 的 HA 并不能保證數(shù)據(jù)完全不丟失,由于 M-S 是異步復制,當 master 節(jié)點異;虮罎ⅲ瑢 slave 切換成 master 后,剛剛沒來得及同步的數(shù)據(jù)就會丟失。另一方面,Codis 支持的 mget/mset 命令是無法保證單點時的原子語義的,如果 mset 指定 KEY 分布在不同 slot 上,從而導致 KEY 在不同機器上,造成要不一起成功,不要一起失敗。所以對于分布式事務的問題,這是一個痛點。在實際場景中,也有人使用了 lua 腳本以擴展 Redis 的功能,雖然 Codis 支持,但是并不保證你的腳本操作的數(shù)據(jù)是否在正確的節(jié)點執(zhí)行,僅僅起到一個轉(zhuǎn)發(fā)功能。如果你并不能保證 lua 操作的 KEY 是否在同一個機器上,Codis 只能將這個腳本分配到參數(shù)列表中的第一個 key 的機器上執(zhí)行。

不支持命令列表,參考

https://github.com/CodisLabs/codis/blob/release3.2/doc/unsupported_cmds.md

Redis 修改部分(增加若干指令),參考

https://github.com/CodisLabs/codis/blob/release3.2/doc/redis_change_zh.md

倔強的青銅

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

幾點改造思路

1. 緩存服務分類。

針對業(yè)務緩存服務不容許數(shù)據(jù)丟失,在現(xiàn)有的邏輯中,Codis 和數(shù)據(jù)庫都會保留,優(yōu)先從 Codis 讀取,如讀取不到時,會從后端數(shù)據(jù)庫里讀取。

針對車次、合作方緩存服務,由于數(shù)據(jù)量大,拉取頻率高的數(shù)據(jù),只會從 Codis 里讀取。

2. 對緩存服務進行接口改造,新增基礎緩存服務層,將生產(chǎn)的 Redis/Codis 相關(guān)的服務納入基礎緩存服務進行統(tǒng)一管理。

 

 

制定一套標準 KEY 命名、管理規(guī)范,包括數(shù)據(jù)類型的選擇、長度、過期時間等。我們會統(tǒng)一在后臺管理系統(tǒng)公示,限定新數(shù)據(jù)的規(guī)則,限制一切不合規(guī)范的行為。

在基礎緩存服務層,對部分 Codis 不支持的命令進行改寫,規(guī)范 Redis/Codis 日常操作。

統(tǒng)計熱點數(shù)據(jù),維護熱點數(shù)據(jù),在基礎緩存服務層上假設二級緩存,作為熱點數(shù)據(jù)的快速通道。

3.SLOT 的分配

哈希算法

Codis 采用 Pre-sharding 的技術(shù)來實現(xiàn)數(shù)據(jù)的分片, 默認分成 1024 個 slots (0-1023), 對于每個 key 來說, 通過以下公式確定所屬的 Slot Id : SlotId = crc32(key) % 1024。例如 pub_cty_ct018 根據(jù)算法得出的值是 997。

 

 

key 值重定向分配

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

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

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

熱點數(shù)據(jù)

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

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

 

 

二級緩存設計

緩存數(shù)據(jù)列表生成與維護

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

 

 

維護本地內(nèi)存中的數(shù)據(jù)

自然統(tǒng)計內(nèi)存緩存: 用 sortedSet 集合,統(tǒng)計各主鍵下的所有鍵 Get 的次數(shù),匯總成 score_{主鍵}方式的集合。利用 ZIncrby 命令統(tǒng)計對應的子鍵的次數(shù),最終匯總每個主鍵,統(tǒng)計出 Top100 的 key,利用 zunionstore 命令將信息統(tǒng)計匯總作為內(nèi)存緩存的基礎,此集合內(nèi)數(shù)據(jù)均從內(nèi)存中獲取。

管理類內(nèi)存緩存: 分析和統(tǒng)計項目主流程的關(guān)鍵的基礎緩存數(shù)據(jù)保存到內(nèi)存中, 保障對應區(qū)域的數(shù)據(jù)獲取與緩存時間,在離開數(shù)據(jù)源后能夠最大程度的展現(xiàn)暢途網(wǎng)的功能。

在發(fā)生手動更新時,對內(nèi)存中對應的主鍵進行更新

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

總結(jié)

多年后,再回想年少時的迷茫和執(zhí)著,或許原因都記不得了。青春就是讓你張揚的笑,也給你莫名的痛。——林語堂《人生不過如此》

經(jīng)過大半年的時間測試、緩存服務接口改造,在 2016 年 9 月份,趕在國慶前,我們的 Codis3.0 上線了,在車次查詢等方面,有了質(zhì)的飛越,尤其節(jié)假日或高峰期期間,平滑的擴縮容、數(shù)據(jù)遷移、高可用等方面展示出巨大優(yōu)勢。

 

 

三個 codis_proxy 節(jié)點的均衡情況:

ipvsadm -Ln
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
FWM 3 rr
-> 192.168.0.**:19000 Local 1 1560 7
-> 192.168.0.**:19000 Route 1 1534 5
-> 192.168.0.**:19000 Route 1 1498 1

1 年后,2018 年 8~9 月份,我們將 Codis 升級到 3.2 的,由之前 6 臺服務器,擴展到 7 臺,實際上多一臺 Codis-web 節(jié)點,獨立承擔 Codis-fe、Codis-dashboard 等組件。對于 Redis-Sentinel、Codis-fe 等組件的引進,解決了運維人員很多問題,在此不再描述,有興趣的可以參考。

https://github.com/CodisLabs/codis/blob/3.2.2/doc/tutorial_zh.md

 

 

標簽: 緩存數(shù)據(jù) 

版權(quán)申明:本站文章部分自網(wǎng)絡,如有侵權(quán),請聯(lián)系:west999com@outlook.com
特別注意:本站所有轉(zhuǎn)載文章言論不代表本站觀點!
本站所提供的圖片等素材,版權(quán)歸原作者所有,如需使用,請與原作者聯(lián)系。

上一篇:10種免費的工具讓你快速的、高效的使用數(shù)據(jù)可視化

下一篇:面試系列:十個海量數(shù)據(jù)處理方法大總結(jié)