集羣技術是構建高性能網站架構的重要手段,試想在網站承受高併發訪問壓力的同時,還須要從海量數據中查詢出知足條件的數據,並快速響應,咱們必然想到的是將數據進行切片,把數據根據某種規則放入多個不一樣的服務器節點,來下降單節點服務器的壓力。 html
上一篇咱們講到了 Redis 的主從複製技術,當實現了多節點的 master-slave 後,咱們也能夠把它叫作集羣,但咱們今天要講的集羣主要是利用切片技術來組建的集羣。 node
集羣要實現的目的是要將不一樣的 key 分散放置到不一樣的 redis 節點,這裏咱們須要一個規則或者算法,一般的作法是獲取 key 的哈希值,而後根據節點數來求模,但這種作法有其明顯的弊端,當咱們須要增長或減小一個節點時,會形成大量的 key 沒法命中,這種比例是至關高的,因此就有人提出了一致性哈希的概念。 redis
一致性哈希有四個重要特徵: 算法
均衡性:也有人把它定義爲平衡性,是指哈希的結果可以儘量分佈到全部的節點中去,這樣能夠有效的利用每一個節點上的資源。 c#
單調性:對於單調性有不少翻譯讓我很是的不解,而我想要的是當節點數量變化時哈希的結果應儘量的保護已分配的內容不會被從新分派到新的節點。 ruby
但一致性哈希不是咱們今天要介紹的重點,由於 Redis 引入另外一種哈希槽(hash slot)的概念。 服務器
Redis 集羣中內置了 16384 個哈希槽,當須要在 Redis 集羣中放置一個 key-value 時,redis 先對 key 使用 crc16 算法算出一個結果,而後把結果對 16384 求餘數,這樣每一個 key 都會對應一個編號在 0-16383 之間的哈希槽,redis 會根據節點數量大體均等的將哈希槽映射到不一樣的節點。 架構
使用哈希槽的好處就在於能夠方便的添加或移除節點。 併發
當須要增長節點時,只須要把其餘節點的某些哈希槽挪到新節點就能夠了; app
當須要移除節點時,只須要把移除節點上的哈希槽挪到其餘節點就好了;
內部機制,與我何干,對於咱們來講,在新增或移除節點的時候不要讓咱們先停掉全部的 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 集羣,好比,如何增長節點,移除節點,從新切片等,敬請期待。