Redis Cluster 4.0 on CentOS 6.9 搭建

集羣簡介

Redis 集羣是一個能夠在多個 Redis 節點之間進行數據共享的設施(installation)。html

Redis 集羣不支持那些須要同時處理多個鍵的 Redis 命令, 由於執行這些命令須要在多個 Redis 節點之間移動數據, 而且在高負載的狀況下, 這些命令將下降 Redis 集羣的性能, 並致使不可預測的行爲。node

Redis 集羣經過分區(partition)來提供必定程度的可用性(availability): 即便集羣中有一部分節點失效或者沒法進行通信, 集羣也能夠繼續處理命令請求。mysql

Redis 集羣提供瞭如下兩個好處:linux

  • 將數據自動切分(split)到多個節點的能力。
  • 當集羣中的一部分節點失效或者沒法進行通信時, 仍然能夠繼續處理命令請求的能力

Redis 集羣數據共享

Redis 集羣使用數據分片(sharding)而非一致性哈希(consistency hashing)來實現: 一個 Redis 集羣包含 16384 個哈希槽(hash slot), 數據庫中的每一個鍵都屬於這 16384 個哈希槽的其中一個, 集羣使用公式 CRC16(key) 16384 來計算鍵 key 屬於哪一個槽, 其中 CRC16(key) 語句用於計算鍵 key 的 CRC16的校驗和 。git

集羣中的每一個節點負責處理一部分哈希槽。 舉個例子, 一個集羣能夠有三個哈希槽, 其中:github

  • 節點 A 負責處理 0 號至 5500 號哈希槽。
  • 節點 B 負責處理 5501 號至 11000 號哈希槽。
  • 節點 C 負責處理 11001 號至 16384 號哈希槽。

這種將哈希槽分佈到不一樣節點的作法使得用戶能夠很容易地向集羣中添加或者刪除節點。 好比說:redis

  • 若是用戶將新節點 D 添加到集羣中, 那麼集羣只須要將節點 A 、B 、 C 中的某些槽移動到節點 D 就能夠了。
  • 與此相似, 若是用戶要從集羣中移除節點 A , 那麼集羣只須要將節點 A 中的全部哈希槽移動到節點 B 和節點 C , 而後再移除空白(不包含任何哈希槽)的節點 A 就能夠了。

由於將一個哈希槽從一個節點移動到另外一個節點不會形成節點阻塞, 因此不管是添加新節點仍是移除已存在節點, 又或者改變某個節點包含的哈希槽數量, 都不會形成集羣下線。sql

Redis 集羣中的主從複製

爲了使得集羣在一部分節點下線或者沒法與集羣的大多數(majority)節點進行通信的狀況下, 仍然能夠正常運做, Redis 集羣對節點使用了主從複製功能: 集羣中的每一個節點都有 1 個至 N 個複製品(replica), 其中一個複製品爲主節點(master), 而其他的 N-1 個複製品爲從節點(slave)。數據庫

在以前列舉的節點 A 、B 、C 的例子中, 若是節點 B 下線了, 那麼集羣將沒法正常運行, 由於集羣找不到節點來處理 5501 號至 11000號的哈希槽。api

另外一方面, 假如在建立集羣的時候(或者至少在節點 B 下線以前), 咱們爲主節點 B 添加了從節點 B1 , 那麼當主節點 B 下線的時候, 集羣就會將 B1 設置爲新的主節點, 並讓它代替下線的主節點 B , 繼續處理 5501 號至 11000 號的哈希槽, 這樣集羣就不會由於主節點 B 的下線而沒法正常運做了。

不過若是節點 B 和 B1 都下線的話, Redis 集羣仍是會中止運做。

開始搭建

 

要讓集羣正常工做至少須要3個主節點,在這裏咱們要建立6個redis節點,其中三個爲主節點,三個爲從節點,對應的redis節點的ip和端口對應關係以下(爲了簡單演示都在同一臺機器上面)

127.0.0.1:7000
127.0.0.1:7001

127.0.0.1:7002

127.0.0.1:7003

127.0.0.1:7004

127.0.0.1:7005

1. 獲取最新版Redis

wget http://download.redis.io/releases/redis-stable.tar.gz

2. 解壓到/usr/local/redis/安裝

# cd /usr/local/redis/
#ls -l
-rw-r--r--  1 root root 131381 Oct  1 20:41 00-RELEASENOTES
-rw-r--r--  1 root root     53 Oct  1 20:41 BUGS
-rw-r--r--  1 root root   1815 Oct  1 20:39 CONTRIBUTING
-rw-r--r--  1 root root   1487 Oct  1 20:39 COPYING
drwxr-xr-x  6 root root   4096 Oct  1 20:41 deps
-rw-r--r--  1 root root     11 Oct  1 20:39 INSTALL
-rw-r--r--  1 root root    151 Oct  1 20:39 Makefile
-rw-r--r--  1 root root   4223 Oct  1 20:39 MANIFESTO
-rw-r--r--  1 root root  20530 Oct  1 20:39 README.md
-rw-r--r--  1 root root  57764 Oct  1 20:39 redis.conf
-rwxr-xr-x  1 root root    271 Oct  1 20:39 runtest
-rwxr-xr-x  1 root root    280 Oct  1 20:39 runtest-cluster
-rwxr-xr-x  1 root root    281 Oct  1 20:39 runtest-sentinel
-rw-r--r--  1 root root   7606 Oct  1 20:39 sentinel.conf
drwxr-xr-x  3 root root   4096 Oct  1 20:41 src
drwxr-xr-x 10 root root   4096 Oct  1 20:41 tests
drwxr-xr-x  8 root root   4096 Oct  1 20:41 utils
#make && make install

 3. 建立目錄

mkdir /data/redis/cluster -p
cd /data/redis/cluster
mkdir 7000 7001 7002 7003 7004 7005

 4. 修改配置文件

cp /usr/local/redis/redis.conf /data/redis/cluster/7000/

修改配置文件中下面選項

port 7000

daemonize yes

cluster-enabled yes

cluster-config-file nodes.conf

cluster-node-timeout 5000

appendonly yes

 

文件中的 cluster-enabled 選項用於開實例的集羣模式, 而 cluster-conf-file 選項則設定了保存節點配置文件的路徑, 默認值爲nodes.conf 。其餘參數相信童鞋們都知道。節點配置文件無須人爲修改, 它由 Redis 集羣在啓動時建立, 並在有須要時自動進行更新。

修改完成後,把修改完成的redis.conf複製到7001-7005目錄下,而且端口修改爲和文件夾對應。

[root@test 7000]# cp redis.conf ../7001/
[root@test 7000]# cp redis.conf ../7002/
[root@test 7000]# cp redis.conf ../7003/
[root@test 7000]# cp redis.conf ../7004/
[root@test 7000]# cp redis.conf ../7005/
# sed -i 's/port 7000/port 7001/g' /data/redis/cluster/7001/redis.conf 
# sed -i 's/port 7000/port 7002/g' /data/redis/cluster/7002/redis.conf 
# sed -i 's/port 7000/port 7003/g' /data/redis/cluster/7003/redis.conf 
# sed -i 's/port 7000/port 7004/g' /data/redis/cluster/7004/redis.conf 
# sed -i 's/port 7000/port 7005/g' /data/redis/cluster/7005/redis.conf 

 5. 啓動6個redis實例

cd /data/redis/cluster/7000
redis-server redis.conf
cd /data/redis/cluster/7001
redis-server redis.conf
cd /data/redis/cluster/7002
redis-server redis.conf
cd /data/redis/cluster/7003
redis-server redis.conf
cd /data/redis/cluster/7004
redis-server redis.conf
cd /data/redis/cluster/7005
redis-server redis.conf

 查看進程狀態

[root@test 7005]# ps -ef|grep redis
root     24873     1  0 21:00 ?        00:00:00 redis-server 127.0.0.1:7001 [cluster]           
root     24898     1  0 21:01 ?        00:00:00 redis-server 127.0.0.1:7000 [cluster]
root     24905     1  0 21:01 ?        00:00:00 redis-server 127.0.0.1:7002 [cluster]
root     24910     1  0 21:01 ?        00:00:00 redis-server 127.0.0.1:7003 [cluster]
root     24915     1  0 21:01 ?        00:00:00 redis-server 127.0.0.1:7004 [cluster]
root     24930     1  0 21:02 ?        00:00:00 redis-server 127.0.0.1:7005 [cluster]

 6. 執行命令建立集羣,首先安裝依賴 

首先要升級Ruby 到2.2 以上的版本

yum remove ruby
wget http://cache.ruby-lang.org/pub/ruby/ruby-2.4.2.zip 按照說明編譯安裝  

安裝rubygems

yum install rubygems -y

安裝gem-redis  (下載地址:https://rubygems.org/gems/redis/versions/4.0.1)

     這裏發現有報錯

[root@test /]# gem install -l redis-4.0.1.gem 
ERROR:  Loading command: install (LoadError)

ERROR:  While executing gem ... (NoMethodError)
    undefined method `invoke_with_build_args' for nil:NilClass

 網上Google 搜到一堆apt-get 的Ubantu 解決方案, 最後在git 上面找到解決辦法

git clone https://github.com/ruby/zlib.git

 而後安裝zlib 包

[root@test zlib]# ruby extconf.rb
checking for deflateReset() in -lz... yes
checking for zlib.h... yes
checking for crc32_combine() in zlib.h... yes
checking for adler32_combine() in zlib.h... yes
checking for z_crc_t in zlib.h... no
creating Makefile
[root@test zlib]# 
[root@test zlib]# make
compiling zlib.c
linking shared-object zlib.so
[root@test zlib]# 
[root@test zlib]# make install
/usr/bin/install -c -m 0755 zlib.so /usr/local/lib/ruby/site_ruby/2.4.0/x86_64-linux

 解決這個問題以後就能夠安裝 redis-4.0.1.gem 了

[root@test/]# gem install -l redis-4.0.1.gem 
Successfully installed redis-4.0.1
Parsing documentation for redis-4.0.1
Installing ri documentation for redis-4.0.1
Done installing documentation for redis after 2 seconds

  7. 使用redis-trib 建立集羣

cp /usr/local/redis/src/redis-trib.rb /usr/local/bin/redis-trib.rb
redis-trib create --replicas 1 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005

命令的意義以下:

  • 給定 redis-trib.rb 程序的命令是 create , 這表示咱們但願建立一個新的集羣。
  • 選項 --replicas 1 表示咱們但願爲集羣中的每一個主節點建立一個從節點。
  • 以後跟着的其餘參數則是實例的地址列表, 咱們但願程序使用這些地址所指示的實例來建立新集羣。

簡單來講, 以上命令的意思就是讓 redis-trib 程序建立一個包含三個主節點和三個從節點的集羣。

接着, redis-trib 會打印出一份預想中的配置給你看, 若是你以爲沒問題的話, 就能夠輸入 yes , redis-trib 就會將這份配置應用到集羣當中:

 

> 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005
>>> Creating cluster
>>> Performing hash slots allocation on 6 nodes...
Using 3 masters:
127.0.0.1:7000
127.0.0.1:7001
127.0.0.1:7002
Adding replica 127.0.0.1:7003 to 127.0.0.1:7000
Adding replica 127.0.0.1:7004 to 127.0.0.1:7001
Adding replica 127.0.0.1:7005 to 127.0.0.1:7002
M: 2909642e736c8510a6b284139de164e5192749f4 127.0.0.1:7000
   slots:0-5460 (5461 slots) master
M: 67c520e08194014965474ffb6ac8e30c8f39fb63 127.0.0.1:7001
   slots:5461-10922 (5462 slots) master
M: d94fc8802b29df1c8601b337df927420492e7179 127.0.0.1:7002
   slots:10923-16383 (5461 slots) master
S: 045c473cb8e416f39444e455151eeff8168bff69 127.0.0.1:7003
   replicates 2909642e736c8510a6b284139de164e5192749f4
S: 079ea3c2c8a4d75cf4e19e6cb6d4a0ccbbb6cd80 127.0.0.1:7004
   replicates 67c520e08194014965474ffb6ac8e30c8f39fb63
S: 6bdaac36d8ea69968b061b44bb47657000340e4c 127.0.0.1:7005
   replicates d94fc8802b29df1c8601b337df927420492e7179
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:7000)
M: 2909642e736c8510a6b284139de164e5192749f4 127.0.0.1:7000
   slots:0-5460 (5461 slots) master
   1 additional replica(s)
M: d94fc8802b29df1c8601b337df927420492e7179 127.0.0.1:7002
   slots:10923-16383 (5461 slots) master
   1 additional replica(s)
S: 045c473cb8e416f39444e455151eeff8168bff69 127.0.0.1:7003
   slots: (0 slots) slave
   replicates 2909642e736c8510a6b284139de164e5192749f4
S: 6bdaac36d8ea69968b061b44bb47657000340e4c 127.0.0.1:7005
   slots: (0 slots) slave
   replicates d94fc8802b29df1c8601b337df927420492e7179
S: 079ea3c2c8a4d75cf4e19e6cb6d4a0ccbbb6cd80 127.0.0.1:7004
   slots: (0 slots) slave
   replicates 67c520e08194014965474ffb6ac8e30c8f39fb63
M: 67c520e08194014965474ffb6ac8e30c8f39fb63 127.0.0.1:7001
   slots:5461-10922 (5462 slots) master
   1 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.

  集羣的客戶端

Redis 集羣現階段的一個問題是客戶端實現不多。 如下是一些網上一些資料:

  • redis-rb-cluster 是antirez編寫的 Ruby 實現, 用於做爲其餘實現的參考。 該實現是對 redis-rb 的一個簡單包裝, 高效地實現了與集羣進行通信所需的最少語義(semantic)。
  • redis-py-cluster 看上去是 redis-rb-cluster 的一個 Python 版本, 這個項目有一段時間沒有更新了(最後一次提交是在六個月以前), 不過能夠將這個項目用做學習集羣的起點。
  • 流行的 Predis 曾經對早期的 Redis 集羣有過必定的支持, 但我不肯定它對集羣的支持是否完整, 也不清楚它是否和最新版本的 Redis 集羣兼容 (由於新版的 Redis 集羣將槽的數量從 4k 改成 16k 了)。
  • Redis unstable 分支中的 redis-cli 程序實現了很是基本的集羣支持, 可使用命令 redis-cli -c 來啓動。

測試 Redis 集羣比較簡單的辦法就是使用 redis-rb-cluster 或者 redis-cli , 接下來咱們將使用 redis-cli 爲例來進行演示:

 

[root@test src]# redis-cli -c -p 7000
127.0.0.1:7000> set name ray
-> Redirected to slot [5798] located at 127.0.0.1:7001
OK
127.0.0.1:7001> 
127.0.0.1:7001> set name2 Tim
-> Redirected to slot [742] located at 127.0.0.1:7000
OK
127.0.0.1:7000> set name3 Andy
OK

  關於redis 支持的數據類型和詳細的命令解釋,能夠參考http://redisdoc.com

[root@test /]# redis-cli -p 7000 cluster nodes
d94fc8802b29df1c8601b337df927420492e7179 127.0.0.1:7002@17002 master - 0 1506867732433 3 connected 10923-16383
045c473cb8e416f39444e455151eeff8168bff69 127.0.0.1:7003@17003 slave 2909642e736c8510a6b284139de164e5192749f4 0 1506867731000 4 connected
6bdaac36d8ea69968b061b44bb47657000340e4c 127.0.0.1:7005@17005 slave d94fc8802b29df1c8601b337df927420492e7179 0 1506867730528 6 connected
079ea3c2c8a4d75cf4e19e6cb6d4a0ccbbb6cd80 127.0.0.1:7004@17004 slave 67c520e08194014965474ffb6ac8e30c8f39fb63 0 1506867730427 5 connected
2909642e736c8510a6b284139de164e5192749f4 127.0.0.1:7000@17000 myself,master - 0 1506867732000 1 connected 0-5460
67c520e08194014965474ffb6ac8e30c8f39fb63 127.0.0.1:7001@17001 master - 0 1506867731530 2 connected 5461-10922

 從上面的輸出能夠看出,集羣由3主3備組成,並且能夠看出誰是誰的主和備,其中第一列是Redis 節點的ID,集羣通訊基於這個惟一的ID 而不是IP 和端口

另外info 命令能夠看出集羣的其餘不少配置信息

127.0.0.1:7002> info
# Server
redis_version:4.0.2
redis_git_sha1:00000000
redis_git_dirty:0
redis_build_id:5d2f34688764aa69
redis_mode:cluster
os:Linux 2.6.32-696.3.2.el6.x86_64 x86_64
arch_bits:64
multiplexing_api:epoll
atomicvar_api:sync-builtin
gcc_version:4.4.7
process_id:24905
run_id:cf77b38c7a0d209d5e86f0c58243b1c81b2b261b
tcp_port:7002
uptime_in_seconds:5094
uptime_in_days:0
hz:10
lru_clock:13695774
executable:/data/redis/cluster/7002/redis-server
config_file:/data/redis/cluster/7002/redis.conf

# Clients
connected_clients:1
client_longest_output_list:0
client_biggest_input_buf:0
blocked_clients:0

# Memory
used_memory:2623728
used_memory_human:2.50M
used_memory_rss:12177408
used_memory_rss_human:11.61M
used_memory_peak:2623728
used_memory_peak_human:2.50M
used_memory_peak_perc:100.04%
used_memory_overhead:2538992
used_memory_startup:1423928
used_memory_dataset:84736
used_memory_dataset_perc:7.06%
total_system_memory:4018335744
total_system_memory_human:3.74G
used_memory_lua:37888
used_memory_lua_human:37.00K
maxmemory:0
maxmemory_human:0B
maxmemory_policy:noeviction
mem_fragmentation_ratio:4.64
mem_allocator:jemalloc-4.0.3
active_defrag_running:0
lazyfree_pending_objects:0

# Persistence
loading:0
rdb_changes_since_last_save:0
rdb_bgsave_in_progress:0
rdb_last_save_time:1506867313
rdb_last_bgsave_status:ok
rdb_last_bgsave_time_sec:0
rdb_current_bgsave_time_sec:-1
rdb_last_cow_size:8572928
aof_enabled:1
aof_rewrite_in_progress:0
aof_rewrite_scheduled:0
aof_last_rewrite_time_sec:-1
aof_current_rewrite_time_sec:-1
aof_last_bgrewrite_status:ok
aof_last_write_status:ok
aof_last_cow_size:0
aof_current_size:0
aof_base_size:0
aof_pending_rewrite:0
aof_buffer_length:0
aof_rewrite_buffer_length:0
aof_pending_bio_fsync:0
aof_delayed_fsync:0

# Stats
total_connections_received:4
total_commands_processed:702
instantaneous_ops_per_sec:0
total_net_input_bytes:85105
total_net_output_bytes:11244
instantaneous_input_kbps:0.02
instantaneous_output_kbps:0.01
rejected_connections:0
sync_full:1
sync_partial_ok:0
sync_partial_err:1
expired_keys:0
evicted_keys:0
keyspace_hits:0
keyspace_misses:1
pubsub_channels:0
pubsub_patterns:0
latest_fork_usec:4435
migrate_cached_sockets:0
slave_expires_tracked_keys:0
active_defrag_hits:0
active_defrag_misses:0
active_defrag_key_hits:0
active_defrag_key_misses:0

# Replication
role:master
connected_slaves:1
slave0:ip=127.0.0.1,port=7005,state=online,offset=952,lag=1
master_replid:6e3d41dcdd4c3c4767affccdd2b2150cb7d3fcd9
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:966
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:966

# CPU
used_cpu_sys:4.53
used_cpu_user:2.50
used_cpu_sys_children:0.01
used_cpu_user_children:0.00

# Cluster
cluster_enabled:1

# Keyspace

  8. Redis 故障測試

嘗試kill 掉7000實例,集羣自動識別並提高對應的slave 爲主

[root@test src]# redis-cli -c -p 7001 cluster nodes
079ea3c2c8a4d75cf4e19e6cb6d4a0ccbbb6cd80 127.0.0.1:7004@17004 slave 67c520e08194014965474ffb6ac8e30c8f39fb63 0 1506868482542 5 connected
2909642e736c8510a6b284139de164e5192749f4 127.0.0.1:7000@17000 master,fail - 1506868460710 1506868460595 1 disconnected
045c473cb8e416f39444e455151eeff8168bff69 127.0.0.1:7003@17003 master - 0 1506868482000 7 connected 0-5460
67c520e08194014965474ffb6ac8e30c8f39fb63 127.0.0.1:7001@17001 myself,master - 0 1506868480000 2 connected 5461-10922
6bdaac36d8ea69968b061b44bb47657000340e4c 127.0.0.1:7005@17005 slave d94fc8802b29df1c8601b337df927420492e7179 0 1506868481000 6 connected
d94fc8802b29df1c8601b337df927420492e7179 127.0.0.1:7002@17002 master - 0 1506868481096 3 connected 10923-16383

嘗試把7000從新啓動,7000並不會去搶佔,而是變成新的slave 加入集羣

[root@test src]# redis-cli -c -p 7001 cluster nodes
079ea3c2c8a4d75cf4e19e6cb6d4a0ccbbb6cd80 127.0.0.1:7004@17004 slave 67c520e08194014965474ffb6ac8e30c8f39fb63 0 1506868670539 5 connected
2909642e736c8510a6b284139de164e5192749f4 127.0.0.1:7000@17000 slave 045c473cb8e416f39444e455151eeff8168bff69 0 1506868672044 7 connected
045c473cb8e416f39444e455151eeff8168bff69 127.0.0.1:7003@17003 master - 0 1506868671542 7 connected 0-5460
67c520e08194014965474ffb6ac8e30c8f39fb63 127.0.0.1:7001@17001 myself,master - 0 1506868671000 2 connected 5461-10922
6bdaac36d8ea69968b061b44bb47657000340e4c 127.0.0.1:7005@17005 slave d94fc8802b29df1c8601b337df927420492e7179 0 1506868670000 6 connected
d94fc8802b29df1c8601b337df927420492e7179 127.0.0.1:7002@17002 master - 0 1506868671040 3 connected 10923-16383

 Redis 除了RDB 以外還有另外一種持久化的方式叫AOF,有點像MySQL 的binlog

[root@test 7000]# ll
total 72
-rw-r--r-- 1 root root   124 Oct  1 22:28 appendonly.aof
-rw-r--r-- 1 root root   205 Oct  1 22:30 dump.rdb
-rw-r--r-- 1 root root   781 Oct  1 22:15 nodes.conf
-rw-r--r-- 1 root root 57758 Oct  1 20:52 redis.conf
[root@test 7000]# more appendonly.aof 
*2
$6 
SELECT
$1 
0
*3
$3 
set
$5 
name2
$3 
Tim
*3
$3 
set
$5 
name3
$4 
Andy
*3
$3 
set
$5 
name2
$4 
Tony

  

最後,想說說Redis 的集羣方案,目前有3大方案:

1. Redis cluster

2. Twemproxy

3. Codis

網上有不少這三種方案的比較,目前最成熟的應該是Codis 由豌豆莢開源,後面會補充Codis 的搭建手冊 https://github.com/CodisLabs/codis/

 

本文主要參考資料:

http://www.cnblogs.com/gomysql/p/4395504.html

http://redisdoc.com/topic/cluster-tutorial.html

相關文章
相關標籤/搜索