1. 程式人生 > >高效能網站架構設計之快取篇(5)- Redis 叢集(上)

高效能網站架構設計之快取篇(5)- Redis 叢集(上)

叢集技術是構建高效能網站架構的重要手段,試想在網站承受高併發訪問壓力的同時,還需要從海量資料中查詢出滿足條件的資料,並快速響應,我們必然想到的是將資料進行切片,把資料根據某種規則放入多個不同的伺服器節點,來降低單節點伺服器的壓力。

上一篇我們講到了 Redis 的主從複製技術,當實現了多節點的 master-slave 後,我們也可以把它叫做叢集,但我們今天要講的叢集主要是利用切片技術來組建的叢集。

叢集要實現的目的是要將不同的 key 分散放置到不同的 redis 節點,這裡我們需要一個規則或者演算法,通常的做法是獲取 key 的雜湊值,然後根據節點數來求模,但這種做法有其明顯的弊端,當我們需要增加或減少一個節點時,會造成大量的 key 無法命中,這種比例是相當高的,所以就有人提出了一致性雜湊的概念。

一致性雜湊有四個重要特徵:

均衡性:也有人把它定義為平衡性,是指雜湊的結果能夠儘可能分佈到所有的節點中去,這樣可以有效的利用每個節點上的資源。

單調性:對於單調性有很多翻譯讓我非常的不解,而我想要的是當節點數量變化時雜湊的結果應儘可能的保護已分配的內容不會被重新分派到新的節點。

分散性和負載:這兩個其實是差不多的意思,就是要求一致性雜湊演算法對 key 雜湊應儘可能的避免重複。

但一致性雜湊不是我們今天要介紹的重點,因為 Redis 引入另一種雜湊槽(hash slot)的概念。

Redis 叢集中內建了 16384 個雜湊槽,當需要在 Redis 叢集中放置一個 key-value 時,redis 先對 key 使用 crc16 演算法算出一個結果,然後把結果對 16384 求餘數,這樣每個 key 都會對應一個編號在 0-16383 之間的雜湊槽,redis 會根據節點數量大致均等的將雜湊槽對映到不同的節點。

使用雜湊槽的好處就在於可以方便的新增或移除節點。

當需要增加節點時,只需要把其他節點的某些雜湊槽挪到新節點就可以了;

當需要移除節點時,只需要把移除節點上的雜湊槽挪到其他節點就行了;

內部機制,與我何干,對於我們來說,在新增或移除節點的時候不要讓我們先停掉所有的 redis 服務我就謝天謝地了,這點它做到了。

下面我們就開始動手搭建一個 redis 叢集來體驗一下。

因為我們要啟動多個 redis 例項,雖然我們可以直接通過命令列來啟動,但始終是不怎麼方便的,所以我們先來新建三個例項目錄,分別是9001,9002,9003,目錄名就是 redis 例項的埠號。

我這裡已經建好了目錄,然後我們把以前編譯過和修改過的 redis-server、redis.conf這兩個檔案分別拷貝到這三個目錄裡面,拷貝完之後就像這樣子了:

我們開啟 redis.conf 檔案,為了簡單起見,我們只保留下面幾個配置項:

daemonize yes
port 9001
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes

注意:port 要修改成對應目錄的名字,也就是每個例項要有不同的埠。

下面我們分別啟動這三個例項:

zhaoguihuadediannao:~ zhaogh$ cd applications/dev/redis-cluster

zhaoguihuadediannao:redis-cluster zhaogh$ cd 9001

zhaoguihuadediannao:9001 zhaogh$ ./redis-server ./redis.conf

zhaoguihuadediannao:9003 zhaogh$ cd ../9002

zhaoguihuadediannao:9002 zhaogh$ ./redis-server ./redis.conf

zhaoguihuadediannao:9002 zhaogh$ cd ../9003

zhaoguihuadediannao:9003 zhaogh$ ./redis-server ./redis.conf

zhaoguihuadediannao:9003 zhaogh$ 

接下來我們來建立叢集,讓三個例項互相通訊:

zhaoguihuadediannao:src zhaogh$ ./redis-trib.rb create --replicas 0 127.0.0.1:9001 127.0.0.1:9002 127.0.0.1:9003

>>> Creating cluster

Connecting to node 127.0.0.1:9001: OK

Connecting to node 127.0.0.1:9002: OK

Connecting to node 127.0.0.1:9003: OK

>>> Performing hash slots allocation on 3 nodes...

Using 3 masters:

127.0.0.1:9001

127.0.0.1:9002

127.0.0.1:9003

M: 92c9912cb1ccf657c886ecd839dd32c66efd8762 127.0.0.1:9001

   slots:0-5460 (5461 slots) master

M: b6d46fcb8b0e6ee373b09a4f2cbcec744d1a259b 127.0.0.1:9002

   slots:5461-10922 (5462 slots) master

M: 44ab30c7c589ffb15b9b04dd827c72cfaeedacb2 127.0.0.1:9003

   slots:10923-16383 (5461 slots) master

Can I set the above configuration? (type 'yes' to accept): yes

>>> Nodes configuration updated

>>> Assign a different config epoch to each node

>>> Sending CLUSTER MEET messages to join the cluster

Waiting for the cluster to join..

>>> Performing Cluster Check (using node 127.0.0.1:9001)

M: 92c9912cb1ccf657c886ecd839dd32c66efd8762 127.0.0.1:9001

   slots:0-5460 (5461 slots) master

M: b6d46fcb8b0e6ee373b09a4f2cbcec744d1a259b 127.0.0.1:9002

   slots:5461-10922 (5462 slots) master

M: 44ab30c7c589ffb15b9b04dd827c72cfaeedacb2 127.0.0.1:9003

   slots:10923-16383 (5461 slots) master

[OK] All nodes agree about slots configuration.

>>> Check for open slots...

>>> Check slots coverage...

[OK] All 16384 slots covered.

zhaoguihuadediannao:src zhaogh$ 

需要注意的是執行 redis-trib.rb 命令需要 ruby 的支援,如果你沒有安裝可以先到 https://rubygems.org/gems/redis 下載,然後離線安裝。

sudo gem install redis-3.0.7.gem --local

下面我們用 redis 自帶的客戶端測試一下:

zhaoguihuadediannao:src zhaogh$ ./redis-cli -c -p 9001

127.0.0.1:9001> get testkey001

-> Redirected to slot [12786] located at 127.0.0.1:9003

(nil)

127.0.0.1:9003> set testkey002 testvalue002

-> Redirected to slot [401] located at 127.0.0.1:9001

OK

127.0.0.1:9001> get testkey002

"testvalue002"

127.0.0.1:9001> set testkey003 testvalue003

OK

127.0.0.1:9001> 

可以看到,雖然我們第一次連線的是9001埠,當我們去獲取 testkey001 的時候,redis cluster 自動幫我們重定向到 9003 。

當我們在 9003 設定 testkey002 時,redis cluster 又重定向到 9001 。

總的來說, redis 叢集部署起來還是非常方便的,遺憾的是,目前幾乎還沒有 c# 的客戶端能很好的支援 redis 叢集,真是非常的悲哀,我們期待他們的更新。

下一遍中,我們繼續討論 redis 叢集,比如,如何增加節點,移除節點,重新切片等,敬請期待。