99精品伊人亚洲|最近国产中文炮友|九草在线视频支援|AV网站大全最新|美女黄片免费观看|国产精品资源视频|精彩无码视频一区|91大神在线后入|伊人终合在线播放|久草综合久久中文

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線(xiàn)課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

從五個(gè)步驟來(lái)講解Redis架構(gòu)設(shè)計(jì)

C語(yǔ)言專(zhuān)家集中營(yíng) ? 2018-01-15 15:51 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

摘要:本文章主要分成五個(gè)步驟內(nèi)容講解

Redis、RedisCluster和Codis;

我們更愛(ài)一致性;

Codis在生產(chǎn)環(huán)境中的使用的經(jīng)驗(yàn)和坑們;

對(duì)于分布式數(shù)據(jù)庫(kù)和分布式架構(gòu)的一些看法;

Q & A環(huán)節(jié)。

Codis是一個(gè)分布式Redis解決方案,與官方的純P2P的模式不同,Codis采用的是Proxy-based的方案。今天我們介紹一下Codis及下一個(gè)大版本RebornDB的設(shè)計(jì),同時(shí)會(huì)介紹一些Codis在實(shí)際應(yīng)用場(chǎng)景中的tips。最后拋磚引玉,會(huì)介紹一下我對(duì)分布式存儲(chǔ)的一些觀點(diǎn)和看法,望各位首席們雅正。
從五個(gè)步驟來(lái)講解Redis架構(gòu)設(shè)計(jì)

一、 Redis,RedisCluster和Codis

Redis:想必大家的架構(gòu)中,Redis已經(jīng)是一個(gè)必不可少的部件,豐富的數(shù)據(jù)結(jié)構(gòu)和超高的性能以及簡(jiǎn)單的協(xié)議,讓Redis能夠很好的作為數(shù)據(jù)庫(kù)的上游緩存層。但是我們會(huì)比較擔(dān)心Redis的單點(diǎn)問(wèn)題,單點(diǎn)Redis容量大小總受限于內(nèi)存,在業(yè)務(wù)對(duì)性能要求比較高的情況下,理想情況下我們希望所有的數(shù)據(jù)都能在內(nèi)存里面,不要打到數(shù)據(jù)庫(kù)上,所以很自然的就會(huì)尋求其他方案。 比如,SSD將內(nèi)存換成了磁盤(pán),以換取更大的容量。更自然的想法是將Redis變成一個(gè)可以水平擴(kuò)展的分布式緩存服務(wù),在Codis之前,業(yè)界只有Twemproxy,但是Twemproxy本身是一個(gè)靜態(tài)的分布式Redis方案,進(jìn)行擴(kuò)容/縮容時(shí)候?qū)\(yùn)維要求非常高,而且很難做到平滑的擴(kuò)縮容。Codis的目標(biāo)其實(shí)就是盡量兼容Twemproxy的基礎(chǔ)上,加上數(shù)據(jù)遷移的功能以實(shí)現(xiàn)擴(kuò)容和縮容,最終替換Twemproxy。從豌豆莢最后上線(xiàn)的結(jié)果來(lái)看,最后完全替換了Twem,大概2T左右的內(nèi)存集群。

Redis Cluster :與Codis同期發(fā)布正式版的官方cluster,我認(rèn)為有優(yōu)點(diǎn)也有缺點(diǎn),作為架構(gòu)師,我并不會(huì)在生產(chǎn)環(huán)境中使用,原因有兩個(gè):

cluster的數(shù)據(jù)存儲(chǔ)模塊和分布式的邏輯模塊是耦合在一起的,這個(gè)帶來(lái)的好處是部署異常簡(jiǎn)單,all-in-the-box,沒(méi)有像Codis那么多概念,組件和依賴(lài)。但是帶來(lái)的缺點(diǎn)是,你很難對(duì)業(yè)務(wù)進(jìn)行無(wú)痛的升級(jí)。比如哪天Redis cluster的分布式邏輯出現(xiàn)了比較嚴(yán)重的bug,你該如何升級(jí)?除了滾動(dòng)重啟整個(gè)集群,沒(méi)什么好辦法。這個(gè)比較傷運(yùn)維。

對(duì)協(xié)議進(jìn)行了較大的修改,對(duì)客戶(hù)端不太友好,目前很多客戶(hù)端已經(jīng)成為事實(shí)標(biāo)準(zhǔn),而且很多程序已經(jīng)寫(xiě)好了,讓業(yè)務(wù)方去更換Redisclient,是不太現(xiàn)實(shí)的,而且目前很難說(shuō)有哪個(gè)Rediscluster客戶(hù)端經(jīng)過(guò)了大規(guī)模生產(chǎn)環(huán)境的驗(yàn)證,從HunanTV開(kāi)源的Rediscluster proxy上可以看得出這個(gè)影響還是蠻大的,否則就會(huì)支持使用cluster的client了。

Codis:和Redis cluster不同的是,Codis采用一層無(wú)狀態(tài)的proxy層,將分布式邏輯寫(xiě)在proxy上,底層的存儲(chǔ)引擎還是Redis本身(盡管基于Redis2.8.13上做了一些小patch),數(shù)據(jù)的分布狀態(tài)存儲(chǔ)于zookeeper(etcd)中,底層的數(shù)據(jù)存儲(chǔ)變成了可插拔的部件。這個(gè)事情的好處其實(shí)不用多說(shuō),就是各個(gè)部件是可以動(dòng)態(tài)水平擴(kuò)展的,尤其無(wú)狀態(tài)的proxy對(duì)于動(dòng)態(tài)的負(fù)載均衡,還是意義很大的,而且還可以做一些有意思的事情,比如發(fā)現(xiàn)一些slot的數(shù)據(jù)比較冷,可以專(zhuān)門(mén)用一個(gè)支持持久化存儲(chǔ)的server group來(lái)負(fù)責(zé)這部分slot,以節(jié)省內(nèi)存,當(dāng)這部分?jǐn)?shù)據(jù)變熱起來(lái)時(shí),可以再動(dòng)態(tài)的遷移到內(nèi)存的server group上,一切對(duì)業(yè)務(wù)透明。比較有意思的是,在Twitter內(nèi)部棄用Twmeproxy后,t家自己開(kāi)發(fā)了一個(gè)新的分布式Redis解決方案,仍然走的是proxy-based路線(xiàn)。不過(guò)沒(méi)有開(kāi)源出來(lái)??刹灏未鎯?chǔ)引擎這個(gè)事情也是Codis的下一代產(chǎn)品RebornDB在做的一件事情。btw,RebornDB和它的持久化引擎都是完全開(kāi)源的,見(jiàn)https://github.com/reborndb/reborn和https://github.com/reborndb/qdb。當(dāng)然這樣的設(shè)計(jì)的壞處是,經(jīng)過(guò)了proxy,多了一次網(wǎng)絡(luò)交互,看上去性能下降了一些,但是記住,我們的proxy是可以動(dòng)態(tài)擴(kuò)展的,整個(gè)服務(wù)的QPS并不由單個(gè)proxy的性能決定(所以生產(chǎn)環(huán)境中我建議使用LVS/HA Proxy或者Jodis),每個(gè)proxy其實(shí)都是一樣的。

二、我們更愛(ài)一致性

很多朋友問(wèn)我,為什么不支持讀寫(xiě)分離,其實(shí)這個(gè)事情的原因很簡(jiǎn)單,因?yàn)槲覀儺?dāng)時(shí)的業(yè)務(wù)場(chǎng)景不能容忍數(shù)據(jù)不一致,由于Redis本身的replication模型是主從異步復(fù)制,在master上寫(xiě)成功后,在slave上是否能讀到這個(gè)數(shù)據(jù)是沒(méi)有保證的,而讓業(yè)務(wù)方處理一致性的問(wèn)題還是蠻麻煩的。而且Redis單點(diǎn)的性能還是蠻高的,不像mysql之類(lèi)的真正的數(shù)據(jù)庫(kù),沒(méi)有必要為了提升一點(diǎn)點(diǎn)讀QPS而讓業(yè)務(wù)方困惑。這和數(shù)據(jù)庫(kù)的角色不太一樣。所以,你可能看出來(lái)了,其實(shí)Codis的HA,并不能保證數(shù)據(jù)完全不丟失,因?yàn)槭钱惒綇?fù)制,所以master掛掉后,如果有沒(méi)有同步到slave上的數(shù)據(jù),此時(shí)將slave提升成master后,剛剛寫(xiě)入的還沒(méi)來(lái)得及同步的數(shù)據(jù)就會(huì)丟失。不過(guò)在RebornDB中我們會(huì)嘗試對(duì)持久化存儲(chǔ)引擎(qdb)可能會(huì)支持同步復(fù)制(syncreplication),讓一些對(duì)數(shù)據(jù)一致性和安全性有更強(qiáng)要求的服務(wù)可以使用。

說(shuō)到一致性,這也是Codis支持的MGET/MSET無(wú)法保證原本單點(diǎn)時(shí)的原子語(yǔ)義的原因。 因?yàn)镸SET所參與的key可能分不在不同的機(jī)器上,如果需要保證原來(lái)的語(yǔ)義,也就是要么一起成功,要么一起失敗,這樣就是一個(gè)分布式事務(wù)的問(wèn)題,對(duì)于Redis來(lái)說(shuō),并沒(méi)有WAL或者回滾這么一說(shuō),所以即使是一個(gè)最簡(jiǎn)單的二階段提交的策略都很難實(shí)現(xiàn),而且即使實(shí)現(xiàn)了,性能也沒(méi)有保證。所以在Codis中使用MSET/MGET其實(shí)和你本地開(kāi)個(gè)多線(xiàn)程SET/GET效果一樣,只不過(guò)是由服務(wù)端打包返回罷了,我們加上這個(gè)命令的支持只是為了更好的支持以前用Twemproxy的業(yè)務(wù)。

在實(shí)際場(chǎng)景中,很多朋友使用了lua腳本以擴(kuò)展Redis的功能,其實(shí)Codis這邊是支持的,但記住,Codis在涉及這種場(chǎng)景的時(shí)候,僅僅是轉(zhuǎn)發(fā)而已,它并不保證你的腳本操作的數(shù)據(jù)是否在正確的節(jié)點(diǎn)上。比如,你的腳本里涉及操作多個(gè)key,Codis能做的就是將這個(gè)腳本分配到參數(shù)列表中的第一個(gè)key的機(jī)器上執(zhí)行。所以這種場(chǎng)景下,你需要自己保證你的腳本所用到的key分布在同一個(gè)機(jī)器上,這里可以采用hashtag的方式。

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

在開(kāi)源Codis后,我們收到了很多社區(qū)的反饋,大多數(shù)的意見(jiàn)是集中在Zookeeper的依賴(lài),Redis的修改,還有為啥需要Proxy上面,我們也在思考,這幾個(gè)東西是不是必須的。當(dāng)然這幾個(gè)部件帶來(lái)的好處毋庸置疑,上面也闡述過(guò)了,但是有沒(méi)有辦法能做得更漂亮。于是,我們?cè)谙乱浑A段會(huì)再往前走一步,實(shí)現(xiàn)以下幾個(gè)設(shè)計(jì):

使用proxy內(nèi)置的Raft來(lái)代替外部的Zookeeper,zk對(duì)于我們來(lái)說(shuō),其實(shí)只是一個(gè)強(qiáng)一致性存儲(chǔ)而已,我們其實(shí)可以使用Raft來(lái)做到同樣的事情。將raft嵌入proxy,來(lái)同步路由信息。達(dá)到減少依賴(lài)的效果。

抽象存儲(chǔ)引擎層,由proxy或者第三方的agent來(lái)負(fù)責(zé)啟動(dòng)和管理存儲(chǔ)引擎的生命周期。具體來(lái)說(shuō),就是現(xiàn)在codis還需要手動(dòng)的去部署底層的Redis或者qdb,自己配置主從關(guān)系什么的,但是未來(lái)我們會(huì)把這個(gè)事情交給一個(gè)自動(dòng)化的agent或者甚至在proxy內(nèi)部集成存儲(chǔ)引擎。這樣的好處是我們可以最大程度上的減小Proxy轉(zhuǎn)發(fā)的損耗(比如proxy會(huì)在本地啟動(dòng)Redis instance)和人工誤操作,提升了整個(gè)系統(tǒng)的自動(dòng)化程度。

還有replication based migration。眾所周知,現(xiàn)在Codis的數(shù)據(jù)遷移方式是通過(guò)修改底層Redis,加入單key的原子遷移命令實(shí)現(xiàn)的。這樣的好處是實(shí)現(xiàn)簡(jiǎn)單、遷移過(guò)程對(duì)業(yè)務(wù)無(wú)感知。但是壞處也是很明顯,首先就是速度比較慢,而且對(duì)Redis有侵入性,還有維護(hù)slot信息給Redis帶來(lái)額外的內(nèi)存開(kāi)銷(xiāo)。大概對(duì)于小key-value為主業(yè)務(wù)和原生Redis是1:1.5的比例,所以還是比較費(fèi)內(nèi)存的。

在RebornDB中我們會(huì)嘗試提供基于復(fù)制的遷移方式,也就是開(kāi)始遷移時(shí),記錄某slot的操作,然后在后臺(tái)開(kāi)始同步到slave,當(dāng)slave同步完后,開(kāi)始將記錄的操作回放,回放差不多后,將master的寫(xiě)入停止,追平后修改路由表,將需要遷移的slot切換成新的master,主從(半)同步復(fù)制,這個(gè)之前提到過(guò)。

三、Codis在生產(chǎn)環(huán)境中的使用的經(jīng)驗(yàn)和坑們

來(lái)說(shuō)一些 tips,作為開(kāi)發(fā)工程師,一線(xiàn)的操作經(jīng)驗(yàn)肯定沒(méi)有運(yùn)維的同學(xué)多,大家一會(huì)可以一起再深度討論。

關(guān)于多產(chǎn)品線(xiàn)部署:很多朋友問(wèn)我們?nèi)绻卸鄠€(gè)項(xiàng)目時(shí),codis如何部署比較好,我們當(dāng)時(shí)在豌豆莢的時(shí)候,一個(gè)產(chǎn)品線(xiàn)會(huì)部署一整套codis,但是zk共用一個(gè),不同的codis集群擁有不同的product name來(lái)區(qū)分,codis本身的設(shè)計(jì)沒(méi)有命名空間那么一說(shuō),一個(gè)codis只能對(duì)應(yīng)一個(gè)product name。不同product name的codis集群在同一個(gè)zk上不會(huì)相互干擾。

關(guān)于zk:由于Codis是一個(gè)強(qiáng)依賴(lài)的zk的項(xiàng)目,而且在proxy和zk的連接發(fā)生抖動(dòng)造成sessionexpired的時(shí)候,proxy是不能對(duì)外提供服務(wù)的,所以盡量保證proxy和zk部署在同一個(gè)機(jī)房。生產(chǎn)環(huán)境中zk一定要是>=3臺(tái)的奇數(shù)臺(tái)機(jī)器,建議5臺(tái)物理機(jī)。

關(guān)于HA:這里的HA分成兩部分,一個(gè)是proxy層的HA,還有底層Redis的HA。先說(shuō)proxy層的HA。之前提到過(guò)proxy本身是無(wú)狀態(tài)的,所以proxy本身的HA是比較好做的,因?yàn)檫B接到任何一個(gè)活著的proxy上都是一樣的,在生產(chǎn)環(huán)境中,我們使用的是jodis,這個(gè)是我們開(kāi)發(fā)的一個(gè)jedis連接池,很簡(jiǎn)單,就是**zk上面的存活proxy列表,挨個(gè)返回jedis對(duì)象,達(dá)到負(fù)載均衡和HA的效果。也有朋友在生產(chǎn)環(huán)境中使用LVS和HA Proxy來(lái)做負(fù)載均衡,這也是可以的。 Redis本身的HA,這里的Redis指的是codis底層的各個(gè)server group的master,在一開(kāi)始的時(shí)候codis本來(lái)就沒(méi)有將這部分的HA設(shè)計(jì)進(jìn)去,因?yàn)镽edis在掛掉后,如果直接將slave提升上來(lái)的話(huà),可能會(huì)造成數(shù)據(jù)不一致的情況,因?yàn)橛行碌男薷目赡茉趍aster中還沒(méi)有同步到slave上,這種情況下需要管理員手動(dòng)的操作修復(fù)數(shù)據(jù)。后來(lái)我們發(fā)現(xiàn)這個(gè)需求確實(shí)比較多的朋友反映,于是我們開(kāi)發(fā)了一個(gè)簡(jiǎn)單的ha工具:codis-ha,用于監(jiān)控各個(gè)server group的master的存活情況,如果某個(gè)master掛掉了,會(huì)直接提升該group的一個(gè)slave成為新的master。 項(xiàng)目的地址是:https://github.com/ngaut/codis-ha。

關(guān)于dashboard:dashboard在codis中是一個(gè)很重要的角色,所有的集群信息變更操作都是通過(guò)dashboard發(fā)起的(這個(gè)設(shè)計(jì)有點(diǎn)像docker),dashboard對(duì)外暴露了一系列RESTfulAPI接口,不管是web管理工具,還是命令行工具都是通過(guò)訪問(wèn)這些httpapi來(lái)進(jìn)行操作的,所以請(qǐng)保證dashboard和其他各個(gè)組件的網(wǎng)絡(luò)連通性。比如,經(jīng)常發(fā)現(xiàn)有用戶(hù)的dashboard中集群的ops為0,就是因?yàn)閐ashboard無(wú)法連接到proxy的機(jī)器的緣故。

關(guān)于go環(huán)境:在生產(chǎn)環(huán)境中盡量使用go1.3.x的版本,go的1.4的性能很差,更像是一個(gè)中間版本,還沒(méi)有達(dá)到production ready的狀態(tài)就發(fā)布了。很多朋友對(duì)go的gc頗有微詞,這里我們不討論哲學(xué)問(wèn)題,選擇go是多方面因素權(quán)衡后的結(jié)果,而且codis是一個(gè)中間件類(lèi)型的產(chǎn)品,并不會(huì)有太多小對(duì)象常駐內(nèi)存,所以對(duì)于gc來(lái)說(shuō)基本毫無(wú)壓力,所以不用考慮gc的問(wèn)題。

關(guān)于隊(duì)列的設(shè)計(jì):其實(shí)簡(jiǎn)單來(lái)說(shuō),就是「不要把雞蛋放在一個(gè)籃子」的道理,盡量不要把數(shù)據(jù)都往一個(gè)key里放,因?yàn)閏odis是一個(gè)分布式的集群,如果你永遠(yuǎn)只操作一個(gè)key,就相當(dāng)于退化成單個(gè)Redis實(shí)例了。很多朋友將Redis用來(lái)做隊(duì)列,但是Codis并沒(méi)有提供BLPOP/BLPUSH的接口,這沒(méi)問(wèn)題,可以將列表在邏輯上拆成多個(gè)LIST的key,在業(yè)務(wù)端通過(guò)定時(shí)輪詢(xún)來(lái)實(shí)現(xiàn)(除非你的隊(duì)列需要嚴(yán)格的時(shí)序要求),這樣就可以讓不同的Redis來(lái)分擔(dān)這個(gè)同一個(gè)列表的訪問(wèn)壓力。而且單key過(guò)大可能會(huì)造成遷移時(shí)的阻塞,由于Redis是一個(gè)單線(xiàn)程的程序,所以遷移的時(shí)候會(huì)阻塞正常的訪問(wèn)。

關(guān)于主從和bgsave:codis本身并不負(fù)責(zé)維護(hù)Redis的主從關(guān)系,在codis里面的master和slave只是概念上的:proxy會(huì)將請(qǐng)求打到「master」上,master掛了codis-ha會(huì)將某一個(gè)「slave」提升成master。而真正的主從復(fù)制,需要在啟動(dòng)底層的Redis時(shí)手動(dòng)的配置。在生產(chǎn)環(huán)境中,我建議master的機(jī)器不要開(kāi)bgsave,也不要輕易的執(zhí)行save命令,數(shù)據(jù)的備份盡量放在slave上操作。

關(guān)于跨機(jī)房/多活:想都別想。。。codis沒(méi)有多副本的概念,而且codis多用于緩存的業(yè)務(wù)場(chǎng)景,業(yè)務(wù)的壓力是直接打到緩存上的,在這層做跨機(jī)房架構(gòu)的話(huà),性能和一致性是很難得到保證的

關(guān)于proxy的部署:其實(shí)可以將proxy部署在client很近的地方,比如同一個(gè)物理機(jī)上,這樣有利于減少延遲,但是需要注意的是,目前jodis并不會(huì)根據(jù)proxy的位置來(lái)選擇位置最佳的實(shí)例,需要修改。

四、對(duì)于分布式數(shù)據(jù)庫(kù)和分布式架構(gòu)的一些看法(one more Thing)

Codis相關(guān)的內(nèi)容告一段落。接下來(lái)我想聊聊我對(duì)于分布式數(shù)據(jù)庫(kù)和分布式架構(gòu)的一些看法。 架構(gòu)師們是如此貪心,有單點(diǎn)就一定要變成分布式,同時(shí)還希望盡可能的透明:P。就MySQL來(lái)看,從最早的單點(diǎn)到主從讀寫(xiě)分離,再到后來(lái)阿里的類(lèi)似Cobar和TDDL,分布式和可擴(kuò)展性是達(dá)到了,但是犧牲了事務(wù)支持,于是有了后來(lái)的OceanBase。Redis從單點(diǎn)到Twemproxy,再到Codis,再到Reborn。到最后的存儲(chǔ)早已和最初的面目全非,但協(xié)議和接口永存,比如SQL和Redis Protocol。

NoSQL來(lái)了一茬又一茬,從HBase到Cassandra到MongoDB,解決的是數(shù)據(jù)的擴(kuò)展性問(wèn)題,通過(guò)裁剪業(yè)務(wù)的存儲(chǔ)和查詢(xún)的模型來(lái)在CAP上平衡。但是幾乎還是都丟掉了跨行事務(wù)(插一句,小米上在HBase上加入了跨行事務(wù),不錯(cuò)的工作)。

我認(rèn)為,拋開(kāi)底層存儲(chǔ)的細(xì)節(jié),對(duì)于業(yè)務(wù)來(lái)說(shuō),KV,SQL查詢(xún)(關(guān)系型數(shù)據(jù)庫(kù)支持)和事務(wù),可以說(shuō)是構(gòu)成業(yè)務(wù)系統(tǒng)的存儲(chǔ)原語(yǔ)。為什么memcached/Redis+mysql的組合如此的受歡迎,正是因?yàn)檫@個(gè)組合,幾個(gè)原語(yǔ)都能用上,對(duì)于業(yè)務(wù)來(lái)說(shuō),可以很方便的實(shí)現(xiàn)各種業(yè)務(wù)的存儲(chǔ)需求,能輕易的寫(xiě)出「正確」的程序。但是,現(xiàn)在的問(wèn)題是數(shù)據(jù)大到一定程度上時(shí),從單機(jī)向分布式進(jìn)化的過(guò)程中,最難搞定的就是事務(wù),SQL支持什么的還可以通過(guò)各種mysqlproxy搞定,KV就不用說(shuō)了,天生對(duì)分布式友好。

于是這樣,我們就默認(rèn)進(jìn)入了一個(gè)沒(méi)有(跨行)事務(wù)支持的世界里,很多業(yè)務(wù)場(chǎng)景我們只能犧牲業(yè)務(wù)的正確性來(lái)在實(shí)現(xiàn)的復(fù)雜度上平衡。比如一個(gè)很簡(jiǎn)單的需求:微博關(guān)注數(shù)的變化,最直白,最正常的寫(xiě)法應(yīng)該是,將被關(guān)注者的被關(guān)注數(shù)的修改和關(guān)注者的關(guān)注數(shù)修改放到同一個(gè)事務(wù)里,一起提交,要么一起成功,要么一起失敗。但是現(xiàn)在為了考慮性能,為了考慮實(shí)現(xiàn)復(fù)雜度,一般來(lái)說(shuō)的做法可能是隊(duì)列輔助異步的修改,或者通過(guò)cache先暫存等等方式繞開(kāi)事務(wù)。

但是在一些需要強(qiáng)事務(wù)支持的場(chǎng)景就沒(méi)有那么好繞過(guò)去了(目前我們只討論開(kāi)源的架構(gòu)方案),比如支付/積分變更業(yè)務(wù),常見(jiàn)的搞法是關(guān)鍵路徑根據(jù)用戶(hù)特征sharding到單點(diǎn)MySQL,或者M(jìn)ySQLXA,但是性能下降得太厲害。

后來(lái)Google在他們的廣告業(yè)務(wù)中遇到這個(gè)問(wèn)題,既需要高性能,又需要分布式事務(wù),還必須保證一致性:),Google在此之前是通過(guò)一個(gè)大規(guī)模的MySQL集群通過(guò)sharding苦苦支撐,這個(gè)架構(gòu)的可運(yùn)維/擴(kuò)展性實(shí)在太差。這要是在一般公司,估計(jì)也就忍了,但是Google可不是一般公司,用原子鐘搞定Spanner,然后再Spanner上構(gòu)建了SQL查詢(xún)層F1。我在第一次看到這個(gè)系統(tǒng)的時(shí)候,感覺(jué)簡(jiǎn)直驚艷,應(yīng)該是第一個(gè)可以真正稱(chēng)為NewSQL的公開(kāi)設(shè)計(jì)的系統(tǒng)。所以,BigTable(KV)+F1(SQL)+Spanner(高性能分布式事務(wù)支持),同時(shí)Spanner還有一個(gè)非常重要的特性是跨數(shù)據(jù)中心的復(fù)制和一致性保證(通過(guò)Paxos實(shí)現(xiàn)),多數(shù)據(jù)中心,剛好補(bǔ)全了整個(gè)Google的基礎(chǔ)設(shè)施的數(shù)據(jù)庫(kù)棧,使得Google對(duì)于幾乎任何類(lèi)型的業(yè)務(wù)系統(tǒng)開(kāi)發(fā)都非常方便。我想,這就是未來(lái)的方向吧,一個(gè)可擴(kuò)展的KV數(shù)據(jù)庫(kù)(作為緩存和簡(jiǎn)單對(duì)象存儲(chǔ)),一個(gè)高性能支持分布式事務(wù)和SQL查詢(xún)接口的分布式關(guān)系型數(shù)據(jù)庫(kù),提供表支持。

五、Q & A

Q1:我沒(méi)看過(guò)Codis,您說(shuō)Codis沒(méi)有多副本概念,請(qǐng)問(wèn)是什么意思?

A1:Codis是一個(gè)分布式Redis解決方案,是通過(guò)presharding把數(shù)據(jù)在概念上分成1024個(gè)slot,然后通過(guò)proxy將不同的key的請(qǐng)求轉(zhuǎn)發(fā)到不同的機(jī)器上,數(shù)據(jù)的副本還是通過(guò)Redis本身保證

Q2:Codis的信息在一個(gè)zk里面存儲(chǔ)著,zk在Codis中還有別的作用嗎?主從切換為何不用sentinel

A2:Codis的特點(diǎn)是動(dòng)態(tài)的擴(kuò)容縮容,對(duì)業(yè)務(wù)透明;zk除了存儲(chǔ)路由信息,同時(shí)還作為一個(gè)事件同步的媒介服務(wù),比如變更master或者數(shù)據(jù)遷移這樣的事情,需要所有的proxy通過(guò)**特定zk事件來(lái)實(shí)現(xiàn) 可以說(shuō)zk被我們當(dāng)做了一個(gè)可靠的rpc的信道來(lái)使用。因?yàn)橹挥屑鹤兏腶dmin時(shí)候會(huì)往zk上發(fā)事件,proxy**到以后,回復(fù)在zk上,admin收到各個(gè)proxy的回復(fù)后才繼續(xù)。本身集群變更的事情不會(huì)經(jīng)常發(fā)生,所以數(shù)據(jù)量不大。Redis的主從切換是通過(guò)codis-ha在zk上遍歷各個(gè)server group的master判斷存活情況,來(lái)決定是否發(fā)起提升新master的命令。

Q3:數(shù)據(jù)分片,是用的一致性hash嗎?請(qǐng)具體介紹下,謝謝。

A3:不是,是通過(guò)presharding,hash算法是crc32(key)%1024

Q4:怎么進(jìn)行權(quán)限管理?

A4:Codis中沒(méi)有鑒權(quán)相關(guān)的命令,在reborndb中加入了auth指令。

Q5:怎么禁止普通用戶(hù)鏈接Redis破壞數(shù)據(jù)?

A5:同上,目前Codis沒(méi)有auth,接下來(lái)的版本會(huì)加入。

Q6:Redis跨機(jī)房有什么方案?

A6:目前沒(méi)有好的辦法,我們的Codis定位是同一個(gè)機(jī)房?jī)?nèi)部的緩存服務(wù),跨機(jī)房復(fù)制對(duì)于Redis這樣的服務(wù)來(lái)說(shuō),一是延遲較大,二是一致性難以保證,對(duì)于性能要求比較高的緩存服務(wù),我覺(jué)得跨機(jī)房不是好的選擇。

Q7:集群的主從怎么做(比如集群S是集群M的從,S和M的節(jié)點(diǎn)數(shù)可能不一樣,S和M可能不在一個(gè)機(jī)房)?

A7:Codis只是一個(gè)proxy-based的中間件,并不負(fù)責(zé)數(shù)據(jù)副本相關(guān)的工作。也就是數(shù)據(jù)只有一份,在Redis內(nèi)部。

Q8:根據(jù)你介紹了這么多,我可以下一個(gè)結(jié)論,你們沒(méi)有多租戶(hù)的概念,也沒(méi)有做到高可用??梢赃@么說(shuō)吧?你們更多的是把Redis當(dāng)做一個(gè)cache來(lái)設(shè)計(jì)。

A8:對(duì),其實(shí)我們內(nèi)部多租戶(hù)是通過(guò)多Codis集群解決的,Codis更多的是為了替換twemproxy的一個(gè)項(xiàng)目。高可用是通過(guò)第三方工具實(shí)現(xiàn)。Redis是cache,Codis主要解決的是Redis單點(diǎn)、水平擴(kuò)展的問(wèn)題。把codis的介紹貼一下: Auto rebalance Extremely simple to use Support both Redis or rocksdb transparently. GUI dashboard & admin tools Supports most of Redis commands. Fully compatible with twemproxy(https://github.com/twitter/twemproxy). Native Redis clients are supported Safe and transparent data migration, Easily add or remove nodes on-demand.解決的問(wèn)題是這些。業(yè)務(wù)不停的情況下,怎么動(dòng)態(tài)的擴(kuò)展緩存層,這個(gè)是codis關(guān)注的。

Q9:對(duì)于Redis冷備的數(shù)據(jù)庫(kù)的遷移,您有啥經(jīng)驗(yàn)沒(méi)有?對(duì)于Redis熱數(shù)據(jù),可以通過(guò)migrate命令實(shí)現(xiàn)兩個(gè)Redis進(jìn)程間的數(shù)據(jù)轉(zhuǎn)移,當(dāng)然如果對(duì)端有密碼,migrate就玩完了(這個(gè)我已經(jīng)給Redis官方提交了patch)。

A9:冷數(shù)據(jù)我們現(xiàn)在是實(shí)現(xiàn)了完整的Redissync協(xié)議,同時(shí)實(shí)現(xiàn)了一個(gè)基于rocksdb的磁盤(pán)存儲(chǔ)引擎,備機(jī)的冷數(shù)據(jù),全部是存在磁盤(pán)上的,直接作為一個(gè)從掛在master上的。實(shí)際使用時(shí),3個(gè)group,keys數(shù)量一致,但其中一個(gè)的ops是另外兩個(gè)的兩倍,有可能是什么原因造成的?key的數(shù)量一致并不代表實(shí)際請(qǐng)求是均勻分布的,不如你可能某幾個(gè)key特別熱,它一定是會(huì)落在實(shí)際存儲(chǔ)這個(gè)key的機(jī)器上的。剛才說(shuō)的rocksdb的存儲(chǔ)引擎:https://github.com/reborndb/qdb,其實(shí)啟動(dòng)后就是個(gè)Redis-server,支持了PSYNC協(xié)議,所以可以直接當(dāng)成Redis從來(lái)用。是一個(gè)節(jié)省從庫(kù)內(nèi)存的好方法。

Q10:Redis實(shí)例內(nèi)存占比超過(guò)50%,此時(shí)執(zhí)行bgsave,開(kāi)了虛擬內(nèi)存支持的會(huì)阻塞,不開(kāi)虛擬內(nèi)存支持的會(huì)直接返回err,對(duì)嗎?

A10:不一定,這個(gè)要看寫(xiě)數(shù)據(jù)(開(kāi)啟bgsave后修改的數(shù)據(jù))的頻繁程度,在Redis內(nèi)部執(zhí)行bgsave,其實(shí)是通過(guò)操作系統(tǒng)COW機(jī)制來(lái)實(shí)現(xiàn)復(fù)制,如果你這段時(shí)間的把幾乎所有的數(shù)據(jù)都修改了,這樣操作系統(tǒng)只能全部完整的復(fù)制出來(lái),這樣就爆了。

Q11:剛讀完,贊一個(gè)??煞窠榻B下codis的autorebalance實(shí)現(xiàn)。

A11:算法比較簡(jiǎn)單,https://github.com/wandoulabs/codis/blob/master/cmd/cconfig/rebalancer.go#L104。代碼比較清楚,code talks:)。其實(shí)就是根據(jù)各個(gè)實(shí)例的內(nèi)存比例,分配slot好的。

Q12:主要想了解對(duì)降低數(shù)據(jù)遷移對(duì)線(xiàn)上服務(wù)的影響,有沒(méi)有什么經(jīng)驗(yàn)介紹?

A12:其實(shí)現(xiàn)在codis數(shù)據(jù)遷移的方式已經(jīng)很溫和了,是一個(gè)個(gè)key的原子遷移,如果怕抖動(dòng)甚至可以加上每個(gè)key的延遲時(shí)間。這個(gè)好處就是對(duì)業(yè)務(wù)基本沒(méi)感知,但是缺點(diǎn)就是慢。

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴

原文標(biāo)題:細(xì)說(shuō)分布式Redis架構(gòu)設(shè)計(jì)和踩過(guò)的那些坑

文章出處:【微信號(hào):C_Expert,微信公眾號(hào):C語(yǔ)言專(zhuān)家集中營(yíng)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    軟件架構(gòu)設(shè)計(jì)教程

    軟件架構(gòu)設(shè)計(jì)教程
    發(fā)表于 09-26 15:27

    汽車(chē)電子電氣架構(gòu)設(shè)計(jì)及優(yōu)化措施

    ??偠灾?,在設(shè)計(jì)與優(yōu)化汽車(chē)電子電氣架構(gòu)時(shí),需要注重市場(chǎng)車(chē)型定位、分析標(biāo)桿車(chē)型、評(píng)估電子電氣架構(gòu)、需求開(kāi)發(fā)及設(shè)計(jì)電子電氣架構(gòu)模型這
    發(fā)表于 10-18 22:10

    Redis主從復(fù)制的作用和步驟

    Redis青銅修煉手冊(cè)() --- Redis的主從復(fù)制
    發(fā)表于 06-27 07:20

    軟件架構(gòu)設(shè)計(jì)的三個(gè)維度

    架構(gòu)設(shè)計(jì)是一個(gè)非常大的話(huà)題,不管寫(xiě)幾篇文章,接觸到的始終只是冰山一角,更多的是實(shí)踐中去體會(huì)。這篇文章主要介紹面向?qū)ο驩O、面向方面AOP和面向服務(wù)SOA這三個(gè)要素在架構(gòu)設(shè)計(jì)中
    發(fā)表于 06-22 10:09 ?1553次閱讀
    軟件<b class='flag-5'>架構(gòu)設(shè)</b>計(jì)的三<b class='flag-5'>個(gè)</b>維度

    基于級(jí)流水線(xiàn)的HEVCDBF模塊硬件架構(gòu)設(shè)計(jì)

    基于級(jí)流水線(xiàn)的HEVCDBF模塊硬件架構(gòu)設(shè)計(jì)_沈高峰
    發(fā)表于 01-07 21:28 ?0次下載

    軟件架構(gòu)設(shè)計(jì)的三個(gè)維度

    架構(gòu)設(shè)計(jì)是一個(gè)非常大的話(huà)題,不管寫(xiě)幾篇文章,接觸到的始終只是冰山一角,更多的是實(shí)踐中去體會(huì)。這篇文章主要介紹面向?qū)ο驩O、面向方面AOP和面向服務(wù)SOA這三個(gè)要素在架構(gòu)設(shè)計(jì)中的位置與作
    發(fā)表于 12-01 11:57 ?700次閱讀
     軟件<b class='flag-5'>架構(gòu)設(shè)</b>計(jì)的三<b class='flag-5'>個(gè)</b>維度

    系統(tǒng)架構(gòu)設(shè)計(jì)的詳細(xì)講解

    上一篇,我們討論了故障度量和安全機(jī)制的ASIL等級(jí)。本篇我們來(lái)聊一聊系統(tǒng)架構(gòu)設(shè)計(jì)相關(guān)內(nèi)容。01系統(tǒng)架構(gòu)設(shè)計(jì)和TSC當(dāng)我們開(kāi)始寫(xiě)TSC時(shí),會(huì)涉及到下圖中一系列的內(nèi)容:當(dāng)我們完成前三期(鏈接見(jiàn)文末)提到的安全機(jī)制規(guī)范后,我們就要開(kāi)始整理好所有的安全需求并在系統(tǒng)
    的頭像 發(fā)表于 12-24 14:33 ?2049次閱讀

    個(gè)步驟,講解PCBA成本如何估算資料下載

    電子發(fā)燒友網(wǎng)為你提供個(gè)步驟,講解PCBA成本如何估算資料下載的電子資料下載,更有其他相關(guān)的電路圖、源代碼、課件教程、中文資料、英文資料、參考設(shè)計(jì)、用戶(hù)指南、解決方案等資料,希望可以幫
    發(fā)表于 04-14 08:54 ?31次下載
    <b class='flag-5'>五</b><b class='flag-5'>個(gè)</b><b class='flag-5'>步驟</b>,<b class='flag-5'>講解</b>PCBA成本如何估算資料下載

    Redis基礎(chǔ)架構(gòu)設(shè)計(jì)及核心網(wǎng)絡(luò)模型架構(gòu)演進(jìn)

    性能優(yōu)異的服務(wù)離不開(kāi)好的架構(gòu)設(shè)計(jì),Redis使用 I/O multiplexing 實(shí)現(xiàn)了單線(xiàn)程接收海量客戶(hù)端請(qǐng)求;通過(guò)單線(xiàn)程Reactor模型實(shí)現(xiàn)了高性能的事件處理
    發(fā)表于 10-11 15:08 ?584次閱讀

    如何寫(xiě)一個(gè)架構(gòu)設(shè)計(jì)

    架構(gòu)設(shè)計(jì)是一個(gè)非常微妙的設(shè)計(jì)領(lǐng)域,它是完全建立在形而上的邏輯上的,它是抽象的,非具象的。但這種抽象必須要以可以實(shí)施為底線(xiàn),否則就淪為紙上談兵了。
    的頭像 發(fā)表于 10-31 10:55 ?1215次閱讀

    3D掃描講解:開(kāi)發(fā)人員可采用的個(gè)基本步驟

    3D掃描講解:開(kāi)發(fā)人員可采用的個(gè)基本步驟
    發(fā)表于 11-03 08:04 ?0次下載
    3D掃描<b class='flag-5'>講解</b>:開(kāi)發(fā)人員可采用的<b class='flag-5'>五</b><b class='flag-5'>個(gè)</b>基本<b class='flag-5'>步驟</b>

    架構(gòu)與微架構(gòu)設(shè)計(jì)

    下面將從芯片的架構(gòu)設(shè)計(jì)、微架構(gòu)設(shè)計(jì)、使用設(shè)計(jì)文檔、設(shè)計(jì)分區(qū)、時(shí)鐘域和時(shí)鐘組、架構(gòu)調(diào)整與性能改進(jìn)、處理器微架構(gòu)設(shè)計(jì)策略等角度進(jìn)行說(shuō)明,并以視頻H.264編碼器設(shè)計(jì)為例。
    的頭像 發(fā)表于 05-08 10:42 ?1562次閱讀
    <b class='flag-5'>架構(gòu)</b>與微<b class='flag-5'>架構(gòu)設(shè)</b>計(jì)

    如何0到1構(gòu)建一個(gè)穩(wěn)定、高性能的Redis集群?

    這個(gè)架構(gòu)非常簡(jiǎn)單,你的業(yè)務(wù)應(yīng)用可以把 Redis 當(dāng)做緩存來(lái)使用, MySQL 中查詢(xún)數(shù)據(jù),然后寫(xiě)入到 Redis 中,之后業(yè)務(wù)應(yīng)用再?gòu)?Redi
    的頭像 發(fā)表于 07-19 15:19 ?819次閱讀
    如何<b class='flag-5'>從</b>0到1構(gòu)建一<b class='flag-5'>個(gè)</b>穩(wěn)定、高性能的<b class='flag-5'>Redis</b>集群?

    Redis架構(gòu)演化之路

    這個(gè)架構(gòu)非常簡(jiǎn)單,你的業(yè)務(wù)應(yīng)用可以把 Redis 當(dāng)做緩存來(lái)使用, MySQL 中查詢(xún)數(shù)據(jù),然后寫(xiě)入到 Redis 中,之后業(yè)務(wù)應(yīng)用再?gòu)?Redi
    的頭像 發(fā)表于 08-03 16:54 ?848次閱讀
    <b class='flag-5'>Redis</b><b class='flag-5'>架構(gòu)</b>演化之路

    redis和rabbitMQ的區(qū)別

    Redis和RabbitMQ之間的區(qū)別。 架構(gòu)設(shè)計(jì): Redis是一個(gè)內(nèi)存存儲(chǔ)系統(tǒng),它將數(shù)據(jù)存儲(chǔ)在內(nèi)存中,以提供快速的讀寫(xiě)訪問(wèn)。因此,Redis
    的頭像 發(fā)表于 12-04 14:48 ?2141次閱讀