1. 程式人生 > >redis叢集 官方方案redis-cluster搭建實戰

redis叢集 官方方案redis-cluster搭建實戰

1.為什麼使用redis?

redis是一種典型的no-sql 即非關係資料庫 像python的字典一樣 儲存key-value鍵值對 工作在memory中

所以很適合用來充當整個網際網路架構中各級之間的cache 比如lvs的4層轉發層 nginx的7層代理層

尤其是lnmp架構應用層如php-fpm或者是Tomcat到mysql之間 做一個cache 以減輕db的壓力

因為有相當一部分的資料 只是簡單的key-value對應關係,而且在實際的業務中常常在短時間內迅速變動 

如果用關係資料庫mysql之類儲存 會大大增加對db的訪問 導致db的負擔很重 因為所有的require中的大部分最後都要匯聚到db

所以如果想要業務穩定 那麼解決db的壓力 就是關鍵 所以現在大部分的解決方案就是在db層之上的各級使用多級的no-sql 

像memcache redis 等 來為db提供緩衝  

2.為什麼使用redis-cluster?

為了在大流量訪問下提供穩定的業務,叢集化是儲存的必然形態

未來的發展趨勢肯定是雲端計算和大資料的緊密結合 只有分散式架構能滿足要求

如果沒有叢集化 何來的分散式?

3.順帶一提總結一波今天的redis原理之資料持久化

雖然redis這種no-sql一般都是作為cache來服務  但是如果完全沒有資料可持久化的方法 那麼顯得有些單薄

就像memcache 由於這種no-sql是工作在memory的 那麼由於memory的實體是ram

所以如果重啟或者宕機 memory中的資料就全沒了 資料的一致性的不到保障 

但是 redis不同 redis有相對的資料持久化的方案 由兩種方式構成 aof & rdb

aof就像關係資料庫中的binlog一樣  把每一次寫操作以追加的形式記錄在其中以檔案的形式刷到磁盤裡 

並且可以使用不同的fsync策略     無fsync,每秒fsync,每次寫的時候fsync.

使用預設的每秒fsync策略,Redis的效能依然很好(fsync是由後臺執行緒進行處理的,主執行緒會盡力處理客戶端請求)

一旦出現故障,最多丟失1秒的資料.

但是缺點也隨之而來 那就是aof檔案的大小會隨著時間線性增長 一段時間之後 就會變得很大 

如果要在一端以AOF的形式來恢復資料 那麼由於AOF檔案的巨大體積 可能會讓程序如同假死一樣 十分的慢

rdb則是一種快照機制 

redis工作在記憶體中 rdb就是每隔一段時間 對記憶體中的資料做一次快照  儲存在rdb檔案中 

而且redis的主從同步可以實現非同步 也是由於rdb的機制 他在做快照時會fork出一個子程序 由子程序來做快照

父程序完全處理請求 毫不影響 很適合資料的備份 

但是問題是 如果資料量很大的話 rdb它要儲存一個完整的資料集 是一個大的工作 如果時間間隔設定的太短 

那麼嚴重影響redis的效能 但是按照常規設定的話 如5分鐘一次 那麼如果宕機或者重啟 就會基於上次做rdb的時間

從而丟失分鐘級的資料

point:在redis4.0的新特性中 採用了aof-rdb的混合方案來保障資料的永續性 但是官方的說法是還不成熟

是一個長期的工作  所以有待觀察吧 

4.redis叢集實現方案: 

關於redis的叢集化方案 目前有三種 

(1)Twitter開發的twemproxy

(2)豌豆莢開發的codis

(3)redis官方的redis-cluster

簡介:twemproxy架構簡單 就是用proxy對後端redis server進行代理 但是由於代理層的消耗效能很低 而且通常涉及多個key的操作都是不支援的 而且本身不支援動態擴容和透明的資料遷移 而且也失去維護 Twitter內部已經不使用了

          redis-cluster是三個裡效能最強大的 因為他使用去中心化的思想 使用hash slot方式 將16348個hash slot 覆蓋到所有節點上 對於儲存的每個key值 使用CRC16(KEY)&16348=slot 得到他對應的hash slot 並在訪問key時就去找他的hash slot在哪一個節點上 然後由當前訪問節點從實際被分配了這個hash slot的節點去取資料 節點之間使用輕量協議通訊 減少頻寬佔用 效能很高 自動實現負載均衡與高可用 自動實現failover  並且支援動態擴充套件 官方已經玩到可以1000個節點 實現的複雜度低 總之個人比較喜歡這個架構 因為他的去中心化思想免去了proxy的消耗 是全新的思路

           但是它也有一些不足 例如官方沒有提供圖形化管理工具 運維體驗差 全手工資料遷移 並且自己對自己本身的redis命令支援也不完全等 但是這些問題 我覺得不能掩蓋他關鍵的新思想所帶來的的優勢 隨著官方的推進 這些問題應該都能在一定時間內得到解決 那麼這時候去中心化思想帶來的高效能就會表現出他巨大的優勢 

          codis使用的也是proxy思路 但是做的比較好 是這兩種之間的一箇中間級 而且支援redis命令是最多的 有圖形化GUI管理和監控工具 運維友好 這個過段時間會詳細另外寫出來原理 工作機制和搭建實現

5.redis-cluster搭建過程

基本上按照官方的文件走 但是其中遇見了不少的坑 而且還遇到一個 應該可以算是官方的坑(完全是官方的疏忽)   /鬧心

所以必須好好的寫出來 

首先下載官方的包 我這裡使用的系統環境是rhel6 並且redis是使用最新版的穩定版4.0.8

然後解壓官方的tar.gz包 的得到redis-4.0.8的目錄

cd ./redis-4.0.8 

vim redis.conf

能起來叢集的配置檔案應該至少如下:

port 7000
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
而且 官方推薦叢集中至少有三個主節點 所以我們建立redis-cluster目錄 然後在其中再建立7000 7001 7002目錄 

在另一臺節點上 同樣建立7003 7004 7005目錄 官方給的叢集實在一臺節點上實現的  因為redis只要有埠就可以起一個程序

所以一臺節點上理論可以起最大埠數支援的redis個數 有多少埠 就可以起多少個獨立的redis-server 我這裡則是在另一臺節點上做其他三個redis-server 所以如果像這樣搭建叢集的話 需要修改每個服務的配置檔案中的bind引數為172.25.xx.xx 就是可以讓其他node訪問的網路IP 而不是預設的127.0.0.1 


然後就是把src路徑中的redis.conf 拷貝到每個剛剛建立的節點資料夾中 並做對應的修改 然後用redis-server redis.conf啟動redis-server


使用netstat命令檢視埠 我這裡起了3個redis-server 700*是供cli訪問的埠 1700*是各個redis之間通訊的埠

我感覺到這樣一個一個切過去啟動十分麻煩 所以寫了一個簡單的shell指令碼一次性啟動當前節點上的配置的所有redis

指令碼如下


兩臺主機的共6個redis-server都起來之後就可以搭建叢集了 這裡官方有建立叢集的指令碼 在原始碼包解壓路徑的

/src 下 名叫redis-trib.rb 我們把它cp到/usr/bin下 方便啟動 

但是這裡如果直接啟動的話 會報錯 因為這個redis-trib.rb是依賴於ruby的 所以我們需要執行 gem install redis

接下來就開始我的慘痛經歷了 

首先沒有gem 於是yum install ruby ruby-devel rpm-build

然後還要自行從網上下載 rubygems的包

好 搞定 執行gem install redis 果斷報錯 

報錯說install redis need ruby version 》=2.2.2

好 yum裡沒有 去到ruby官網下載ruby-2.2.9 原始碼包 tar zxf 解壓 

./configure --prefix=/usr/local/ruby  

make && make install

安裝完成 rm -rf /usr/bin/ruby 刪掉原來舊版本的ruby    再 ln -s /usr/local/ruby/bin/ruby    /usr/bin 

把新版ruby 連線過去

執行 ruby -v    顯示ruby版本 是2.2.9 成功 

再次執行gem install redis 

果斷又報錯 !!

報錯說ruby 找不到zlib庫 好 yum install zlib 再次執行 geminstall 

依舊報錯 ! 查了下攻略 說要用ruby原始碼包裡./ext/zlib 自帶的zlib庫

cd  ruby-2.2.9/ext/zlib  執行ruby ./extconf.mk    本來想著應該看到create makefile 然後make && make install就OK

再次報錯!!! 輸出

check ******* z   no

check ********zlib    no

check ********* zlib1    no

check *********  libz    no         can't  create makefile

咋回事啊? 啥玩意啊? 我在這瞬間矇蔽了

又去查攻略 找不到相似問題 折騰到1點 無果

今天冷靜下來後 機智的我 vim extconf.mk 這個檔案 進去看看咋回事 

發現有這樣的ruby語句 本人雖然不懂ruby但是有一定程式設計功底 大概看懂了這個語句的邏輯

 就是他 迴圈check (z |zlib |zlib1| libz )& if source path have zlib.h    then  return yes     

else return no 

然後瞬間想到 可能是我沒有這個zlib.h 才導致返回no 因為之前 yum install 的zlib庫裡有zlib.so模組  

於是 yum provides */zlib.h   發現了zlib-devel這個包提供這個檔案

果斷 yum install zlib-devel   再次進入/ruby-2.2.9/ext/zlib 執行 ruby  ./extconf.mk 

直接返回4個yes    creating Makefile  

之後make && make install  看到他就是把一個模組連結到了 ruby家目錄下的lib/zlib裡 

問題解決

終於可以再次執行 gem install redis了   流淚

還沒流完淚  再次報錯!!

ruby又需要openssl了    好 yum install openssl openssl-devel   -y

重新執行 還是報錯 看來ruby只認從他原始碼目錄安裝的模組  果斷進入/ruby-2.2.9/ext/  發現果然有openssl這個目錄

cd 進入 執行 ruby ./extconf.mk           這次沒有報錯 直接create Makefile

歡喜進行make 然後猝不及防的報錯!!!

make ** can' make target /include/ruby.h , need "ossl_pkey.o"  大概是這樣

一波折騰 沒搞出來 最後查到一個國外的論壇上 看到國外大神解答 說這個是因為Makefile裡面官方忘了給路徑變數賦值 

需要在Makefile裡面新增一行  top_srcdir = ../..

果斷vim /ruby-2.2.9/ext/openssl/Makefile  新增這一行 然後 繼續make && make install 終於成功

這下終於可以gem install redis了       難受 上圖 


終於成功 然後按照官方命令 

./redis-trib.rb create --replicas 1 172.25.44.1:7000 172.25.44.1:7001 \
172.25.44.1:7002 172.25.44.2:7003 172.25.44.2:7004 172.25.44.2:7005
啟動叢集!!!


看到 All 16384 slots coverd  所有的16384個雜湊槽覆蓋完成   表示叢集啟動成功

測試 使用 redis-cli   -c(表示連線到叢集 )-h 172.25.44.1(指定IP) -p 7000(指定埠)   連線到叢集 進行測試


從terminal的輸出就能看到 叢集的hash slot工作模式 叢集成功