Redis高可用,高性能,高並發


  • 高性能,指的是查詢快

  redis是c語言實現,與其他語言相比,在實現語言層面性能高;redis是內存數據庫,而傳統的關系型數據庫是磁盤文件讀寫,所以redis讀寫快;單線程,無上下文切換損耗,也不需要線程間同步,在單核cpu上,性能高,如果服務器是多核cpu,可以開啟多個進程的單線程redis實例;基於以上原因,才達到了官網所說的,即使pc都支持QPS>10w/s的查詢。

  • 高可用(High Availability),高可用指的是在節點故障時,服務仍然能正常運行或者進行降級后提供部分服務

  單點redis:redis是內存數據庫,在遇到斷電或者重啟時,數據能恢復嗎?當然能。redis提供了兩種持久化方式AOF/RDB,AOF是Append Of File,redis的修改命令(hset、set)會寫入文件中,在恢復數據時,從頭執行一遍命令就恢復了數據了,這種數據最全,但是恢復時間長。RDB是Redis DataBase,redis會定時備份數據,這是默認的持久化方式,但是因為是定時備份所有數據會有部分缺失。
  master-slave(主從.復制):如果單點redis遇到故障怎么辦?redis提供master-slave/sentinel/cluster高可用方案,master-slave是常見的復制(Replication) 方案,一個master,多個slave,就是俗稱的主從復制,master用來接收請求,slave備份master數據,冗余了數據,但master-slave有個缺點,master 故障后,slave不會自動切換為master,必須人為干預,sentinel就是用來解決這個問題的
  sentinel(哨兵):這種方案在master-slave的基礎上,多了sentinel[ˈsentɪnl],sentinel漢語意思是哨兵,哨兵監測master及所有的slave狀態(心跳),如果master故障,sentinel會組織slave選舉新的master,並通知客戶端,從而實現可用性,但是單master畢竟能力有限(查詢最大10w/s),如果超過這個極限,怎么辦?我們會想,如果有多個master就好了,這就是集群

  • 高並發(redis cluster.集群)

  redis集群有2個TCP 端口,一個用來伺服客戶端,比如常見的6379,另外一個對6379+10000=16379,作為“high”端口,high端口用來節點間通信、失敗監測、故障轉移授權、配置更新,high端口與數據端口差值必須是固定的10000。redis集群對數據做了分片,redis數據分片沒有采用一致性哈希(consistent hash),而是使用了hash slot,redis集群一共有16384(2的14次方)個槽,key對16384取模分配,比如A、B、C三個節點,
節點A 哈希槽( 0 ~ 5500)
節點 B 哈希槽(5501 ~ 11000)
節點 C哈希槽( 11001 ~ 16383)
增加節點D,那么就要將A、B、C的部分數據遷移到D上;如果刪除A,那就要將A的數據遷移到B、C上,然后才能完全刪除A。為了增加可用性,每個節點使用主從復制,比如A1、B1、C1,當B節點故障時,集群會將B1設置為新master,當B1也故障時,集群就真down了

replication(主從.復制)

  如果業務要承載的QPS在幾十萬,單機是不可能做到的,此時就可以用到復制。做一個主從架構,一主多從,master節點負責寫,slave節點負責讀,假如說一個節點可以承載的5w讀QPS,那么兩個節點就可以承載10w的讀QPS,水平擴容非常方便。

  master節點掛太多slave節點會有性能問題,此時就可以在slave節點上掛slave節點

redis replication(主從復制)的核心機制有如下幾點:

  • redis采用異步方式復制數據到slave node,不會block master node的正常工作
  • 一個master node可以配置多個slave node,slave node也可以連接其他的slave node
  • slave node主要用來進行橫向擴容,做讀寫分離,擴容的slave node可以提高讀的吞吐量

主從復制原理:

  • slave連接master,發送SYNC命令;
  • master接收到SYNC命名后,開始執行BGSAVE命令生成RDB文件並使用緩沖區記錄此后執行的所有寫命令;
  • master BGSAVE執行完后,向slave發送快照文件,並在發送期間繼續記錄被執行的寫命令;
  • slave收到快照文件后丟棄所有舊數據,載入收到的快照;
  • master快照發送完畢后開始向salve發送緩沖區中的寫命令;
  • slave完成對快照的載入,開始接收命令請求,並執行來自主服務器緩沖區的寫命令(從服務器初始化完成
  • master每執行一個寫命令就會向slave發送相同的寫命令,slave接收並執行收到的寫命令(從服務器初始化完成后的操作

主從復制優缺點:

優點:

  • 支持主從復制,主機會自動將數據同步到從機,可以進行讀寫分離
  • 為了分載Master的讀操作壓力,Slave服務器可以為客戶端提供只讀操作的服務,寫服務仍然必須由Master來完成
  • Slave同樣可以接受其它Slaves的連接和同步請求,這樣可以有效的分載Master的同步壓力。
  • Master Server是以非阻塞的方式為Slaves提供服務。所以在Master-Slave同步期間,客戶端仍然可以提交查詢或修改請求。
  • Slave Server同樣是以非阻塞的方式完成數據同步。在同步期間,如果有客戶端提交查詢請求,Redis則返回同步之前的數據

缺點:

  • Redis不具備自動容錯和恢復功能,主機從機的宕機都會導致前端部分讀寫請求失敗,需要等待機器重啟或者手動切換前端的IP才能恢復。
  • 主機宕機,宕機前有部分數據未能及時同步到從機,切換IP后還會引入數據不一致的問題,降低了系統的可用性。
  • Redis較難支持在線擴容,在集群容量達到上限時在線擴容會變得很復雜。

sentinel(哨兵)

  主從架構有一個缺點就是如果master節點掛了,那么寫服務是不可用的,因為slave節點默認是只讀的,這時就重啟master節點或者重新配置主從,有沒有更好的方案呢?類似zookeeper的組件,能自動完成主從切換。在Redis中還真有,就是sentinel節點,當master節點發生故障能自動完成主從切換。

  當master節點掛掉時,sentinel將一個slave節點變成maste節點,當原先的master節點可用時,以slave的角色加入集群。
一個高可用的系統是很忌諱有單點問題的。看到沒,sentinel就是一個單點,如果sentinel掛了,主從切換也就沒人做了。所以應該將sentinel也做成一個集群,其部署架構主要包括兩部分:Redis Sentinel 集群和 Redis 數據集群。

  其中 Redis Sentinel 集群是由若干 Sentinel 節點組成的分布式集群,可以實現故障發現、故障自動轉移、配置中心和客戶端通知。Redis Sentinel 的節點數量要滿足 2n+1(n>=1)的奇數個。

哨兵的作用有如下幾點

  • 集群監控,負責監控redis master和slave進程是否正常工作
  • 消息通知,如果某個redis實例有故障,那么哨兵負責發送消息作為報警通知給管理員
  • 故障轉移,如果master node掛掉了,會自動轉移到slave node上
  • 配置中心,客戶端初始化時,通過哨兵獲得master地址,如果故障轉移發生了,通知客戶端新的master地址

哨兵的工作方式:

  • 每個Sentinel(哨兵)進程以每秒鍾一次的頻率向整個集群中的Master主服務器,Slave從服務器以及其他Sentinel(哨兵)進程發送一個 PING 命令。
  • 如果一個實例(instance)距離最后一次有效回復 PING 命令的時間超過 down-after-milliseconds 選項所指定的值, 則這個實例會被 Sentinel(哨兵)進程標記為主觀下線(SDOWN)
  • 如果一個Master主服務器被標記為主觀下線(SDOWN),則正在監視這個Master主服務器的所有 Sentinel(哨兵)進程要以每秒一次的頻率確認Master主服務器的確進入了主觀下線狀態
  • 當有足夠數量的 Sentinel(哨兵)進程(大於等於配置文件指定的值)在指定的時間范圍內確認Master主服務器進入了主觀下線狀態(SDOWN), 則Master主服務器會被標記為客觀下線(ODOWN)
  • 在一般情況下, 每個 Sentinel(哨兵)進程會以每 10 秒一次的頻率向集群中的所有Master主服務器、Slave從服務器發送 INFO 命令。
  • 當Master主服務器被 Sentinel(哨兵)進程標記為客觀下線(ODOWN)時,Sentinel(哨兵)進程向下線的 Master主服務器的所有 Slave從服務器發送 INFO 命令的頻率會從 10 秒一次改為每秒一次。
  • 若沒有足夠數量的 Sentinel(哨兵)進程同意 Master主服務器下線, Master主服務器的客觀下線狀態就會被移除。若 Master主服務器重新向 Sentinel(哨兵)進程發送 PING 命令返回有效回復,Master主服務器的主觀下線狀態就會被移除。

 哨兵模式的優缺點

優點:

  • 哨兵模式是基於主從模式的,所有主從的優點,哨兵模式都具有。
  • 主從可以自動切換,系統更健壯,可用性更高。

缺點:

  • Redis較難支持在線擴容,在集群容量達到上限時在線擴容會變得很復雜

redis cluster(集群)

  redis的哨兵模式基本已經可以實現高可用,讀寫分離 ,但是在這種模式下每台redis服務器都存儲相同的數據,很浪費內存,因為一個master節點並不能放海量數據,而且單個Redis的實例過大時,會導致rdb文件過大,當執行主從同步時時間過長,所以在redis3.0上加入了cluster模式,實現的redis的分布式存儲,也就是說每台redis節點上存儲不同的內容。

 

 

 

 Redis-Cluster采用無中心結構,它的特點如下:

  • 所有的redis節點彼此互聯(PING-PONG機制),內部使用二進制協議優化傳輸速度和帶寬。

  • 節點的fail是通過集群中超過半數的節點檢測失效時才生效。

  • 客戶端與redis節點直連,不需要中間代理層.客戶端不需要連接集群所有節點,連接集群中任何一個可用節點即可。

工作方式:

  在redis的每一個節點上,都有這么兩個東西,一個是插槽(slot),它的的取值范圍是:0-16383。還有一個就是cluster,可以理解為是一個集群管理的插件。當我們的存取的key到達的時候,redis會根據crc16的算法得出一個結果,然后把結果對 16384 求余數,這樣每個 key 都會對應一個編號在 0-16383 之間的哈希槽,通過這個值,去找到對應的插槽所對應的節點,然后直接自動跳轉到這個對應的節點上進行存取操作。

  為了保證高可用,redis-cluster集群引入了主從模式,一個主節點對應一個或者多個從節點,當主節點宕機的時候,就會啟用從節點。當其它主節點ping一個主節點A時,如果半數以上的主節點與A通信超時,那么認為主節點A宕機了。如果主節點A和它的從節點A1都宕機了,那么該集群就無法再提供服務了。

優點:

  • 無中心架構;
  • 數據按照 slot 存儲分布在多個節點,節點間數據共享,可動態調整數據分布;
  • 可擴展性:可線性擴展到 1000 多個節點,節點可動態添加或刪除;
  • 高可用性:部分節點不可用時,集群仍可用。通過增加 Slave 做 standby 數據副本,能夠實現故障自動 failover,節點之間通過 gossip 協議交換狀態信息,用投票機制完成 Slave 到 Master 的角色提升;
  • 降低運維成本,提高系統的擴展性和可用性。

缺點:

  • Client 實現復雜,驅動要求實現 Smart Client,緩存 slots mapping 信息並及時更新,提高了開發難度,客戶端的不成熟影響業務的穩定性。目前僅 JedisCluster 相對成熟,異常處理部分還不完善,比如常見的“max redirect exception”。
  • 節點會因為某些原因發生阻塞(阻塞時間大於 clutser-node-timeout),被判斷下線,這種 failover 是沒有必要的。
  • 數據通過異步復制,不保證數據的強一致性。
  • 多個業務使用同一套集群時,無法根據統計區分冷熱數據,資源隔離性較差,容易出現相互影響的情況。
  • Slave 在集群中充當“冷備”,不能緩解讀壓力,當然可以通過 SDK 的合理設計來提高 Slave 資源的利用率。
  • Key 批量操作限制,如使用 mset、mget 目前只支持具有相同 slot 值的 Key 執行批量操作。對於映射為不同 slot 值的 Key 由於 Keys 不支持跨 slot 查詢,所以執行 mset、mget、sunion 等操作支持不友好。
  • Key 事務操作支持有限,只支持多 key 在同一節點上的事務操作,當多個 Key 分布於不同的節點上時無法使用事務功能。
  • Key 作為數據分區的最小粒度,不能將一個很大的鍵值對象如 hash、list 等映射到不同的節點。
  • 不支持多數據庫空間,單機下的 redis 可以支持到 16 個數據庫,集群模式下只能使用 1 個數據庫空間,即 db 0。
  • 復制結構只支持一層,從節點只能復制主節點,不支持嵌套樹狀復制結構。
  • 避免產生 hot-key,導致主庫節點成為系統的短板。
  • 避免產生 big-key,導致網卡撐爆、慢查詢等。
  • 重試時間應該大於 cluster-node-time 時間。
  • Redis Cluster 不建議使用 pipeline 和 multi-keys 操作,減少 max redirect 產生的場景。
接下來重點對比Redis三大集群解決方案對比,Twemproxy VS Codis VS Redis-cluster
Redis集群三種常見的解決方案:

  1、客戶端分片:這種方案將分片工作放在業務程序端,程序代碼根據預先設置的路由規則,直接對多個Redis實例進行分布式訪問。這樣的好處是,不依賴於第三方分布式中間件,實現方法和代碼都自己掌控,可隨時調整,不用擔心踩到坑。這實際上是一種靜態分片技術。Redis實例的增減,都得手工調整分片程序。基於此分片機制的開源產品,現在仍不多見。這種分片機制的性能比代理式更好(少了一個中間分發環節)。但缺點是升級麻煩,對研發人員的個人依賴性強——需要有較強的程序開發能力做后盾。如果主力程序員離職,可能新的負責人,會選擇重寫一遍。所以,這種方式下,可運維性較差。出現故障,定位和解決都得研發和運維配合着解決,故障時間變長。因此這種方案,難以進行標准化運維,不太適合中小公司(除非有足夠的DevOPS)。

  2、代理 分片:這種方案,將分片工作交給專門的代理程序來做。代理程序接收到來自業務程序的數據請求,根據路由規則,將這些請求分發給正確的Redis實例並返回給業務程序。這種機制下,一般會選用第三方代理程序(而不是自己研發),因為后端有多個Redis實例,所以這類程序又稱為分布式中間件。這樣的好處是,業務程序不用關心后端Redis實例,運維起來也方便。雖然會因此帶來些性能損耗,但對於Redis這種內存讀寫型應用,相對而言是能容忍的。這是我們推薦的集群實現方案。像基於該機制的開源產品Twemproxy,Codis便是其中代表,應用非常廣泛。
  3、服務器端分片:建立在基於無中心分布式架構之上(沒有代理節點性能瓶頸問題)。Redis-Cluster即為官方基於該架構的解決方案。Redis Cluster將所有Key映射到16384個Slot中,集群中每個Redis實例負責一部分,業務程序通過集成的Redis Cluster客戶端進行操作。客戶端可以向任一實例發出請求,如果所需數據不在該實例中,則該實例引導客戶端自動去對應實例讀寫數據。Redis Cluster的成員管理(節點名稱、IP、端口、狀態、角色)等,都通過節點之間兩兩通訊,定期交換並更新。
 
接下來分別講解各解決方案代表產品實現方式優缺點:
Twemproxy:

  Twemproxy是一種代理分片機制,由Twitter開源。Twemproxy作為代理,可接受來自多個程序的訪問,按照路由規則,轉發給后台的各個Redis服務器,再原路返回。這個方案順理成章地解決了單個Redis實例承載能力的問題。當然,Twemproxy本身也是單點,需要用Keepalived做高可用方案。這么些年來,Twemproxy是應用范圍最廣、穩定性最高、最久經考驗的分布式中間件。只是,他還有諸多不方便之處。Twemproxy最大的痛點在於,無法平滑地擴容/縮容。這樣增加了運維難度:業務量突增,需增加Redis服務器;業務量萎縮,需要減少Redis服務器。但對Twemproxy而言,基本上都很難操作。或者說,Twemproxy更加像服務器端靜態sharding。有時為了規避業務量突增導致的擴容需求,甚至被迫新開一個基於Twemproxy的Redis集群。Twemproxy另一個痛點是,運維不友好,甚至沒有控制面板。

Codis:

  Codis由豌豆莢於2014年11月開源,基於Go和C開發,是近期涌現的、國人開發的優秀開源軟件之一。現已廣泛用於豌豆莢的各種Redis業務場景,從各種壓力測試來看,穩定性符合高效運維的要求。性能更是改善很多,最初比Twemproxy慢20%;現在比Twemproxy快近100%(條件:多實例,一般Value長度)。Codis具有可視化運維管理界面。Codis無疑是為解決Twemproxy缺點而出的新解決方案。因此綜合方面會由於Twemproxy很多。目前也越來越多公司選擇Codis。Codis引入了Group的概念,每個Group包括1個Redis Master及至少1個Redis Slave,這是和Twemproxy的區別之一。這樣做的好處是,如果當前Master有問題,則運維人員可通過Dashboard“自助式”切換到Slave,而不需要小心翼翼地修改程序配置文件。為支持數據熱遷移(Auto Rebalance),出品方修改了Redis Server源碼,並稱之為Codis Server。Codis采用預先分片(Pre-Sharding)機制,事先規定好了,分成1024個slots(也就是說,最多能支持后端1024個Codis Server),這些路由信息保存在ZooKeeper中。

Redis-cluster:

  reids-cluster在redis3.0中推出,支持Redis分布式集群部署模式。采用無中心分布式架構。所有的redis節點彼此互聯(PING-PONG機制),內部使用二進制協議優化傳輸速度和帶寬.節點的fail是通過集群中超過半數的節點檢測失效時才生效.客戶端與redis節點直連,不需要中間proxy層.客戶端不需要連接集群所有節點,連接集群中任何一個可用節點即可,減少了代理層,大大提高了性能。redis-cluster把所有的物理節點映射到[0-16383]slot上,cluster 負責維護node<->slot<->key之間的關系。目前Jedis已經支持Redis-cluster。從計算架構或者性能方面無疑Redis-cluster是最佳的選擇方案。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM