Redis集群的原理和搭建

前言

Redis 是我們目前大規模使用的緩存中間件,由于它強大高效而又便捷的功能,得到了廣泛的使用。單節點的Redis已經就達到了很高的性能,為了提高可用性我們可以使用Redis集群。本文參考了Rdis的官方文檔和使用Redis官方提供的Redis Cluster工具搭建Rdis集群。

注意 :Redis的版本要在3.0以上,截止今天,Redis的版本是3.2.9,本教程也使用3.2.9作為教程

Redis集群的概念

介紹

Redis 集群是一個可以在多個 Redis 節點之間進行數據共享的設施(installation)。

Redis 集群不支持那些需要同時處理多個鍵的 Redis 命令, 因為執行這些命令需要在多個 Redis 節點之間移動數據, 并且在高負載的情況下, 這些命令將降低 Redis 集群的性能, 并導致不可預測的錯誤。

Redis 集群通過分區(partition)來提供一定程度的可用性(availability): 即使集群中有一部分節點失效或者無法進行通訊, 集群也可以繼續處理命令請求。

Redis 集群提供了以下兩個好處:

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

數據分片

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

集群中的每個節點負責處理一部分哈希槽。 舉個例子, 一個集群可以有三個哈希槽, 其中:

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

這種將哈希槽分布到不同節點的做法使得用戶可以很容易地向集群中添加或者刪除節點。 比如說:
我現在想設置一個key,叫my_name:

set my_name zhangguoji

按照Redis Cluster的哈希槽算法,CRC16('my_name')%16384 = 2412 那么這個key就被分配到了節點A上
同樣的,當我連接(A,B,C)的任意一個節點想獲取my_name這個key,都會轉到節點A上
再比如
如果用戶將新節點 D 添加到集群中, 那么集群只需要將節點 A 、B 、 C 中的某些槽移動到節點 D 就可以了。
增加一個D節點的結果可能如下:

  • 節點A覆蓋1365-5460
  • 節點B覆蓋6827-10922
  • 節點C覆蓋12288-16383
  • 節點D覆蓋0-1364,5461-6826,10923-1228

與此類似, 如果用戶要從集群中移除節點 A , 那么集群只需要將節點 A 中的所有哈希槽移動到節點 B 和節點 C , 然后再移除空白(不包含任何哈希槽)的節點 A 就可以了。
因為將一個哈希槽從一個節點移動到另一個節點不會造成節點阻塞, 所以無論是添加新節點還是移除已存在節點, 又或者改變某個節點包含的哈希槽數量, 都不會造成集群下線。
所以,Redis Cluster的模型大概是這樣的形狀


082248582749859.jpg

主從復制模型

為了使得集群在一部分節點下線或者無法與集群的大多數(majority)節點進行通訊的情況下, 仍然可以正常運作, Redis 集群對節點使用了主從復制功能: 集群中的每個節點都有 1 個至 N 個復制品(replica), 其中一個復制品為主節點(master), 而其余的 N-1 個復制品為從節點(slave)。

在之前列舉的節點 A 、B 、C 的例子中, 如果節點 B 下線了, 那么集群將無法正常運行, 因為集群找不到節點來處理 5501 號至 11000號的哈希槽。

另一方面, 假如在創建集群的時候(或者至少在節點 B 下線之前), 我們為主節點 B 添加了從節點 B1 , 那么當主節點 B 下線的時候, 集群就會將 B1 設置為新的主節點, 并讓它代替下線的主節點 B , 繼續處理 5501 號至 11000 號的哈希槽, 這樣集群就不會因為主節點 B 的下線而無法正常運作了。

不過如果節點 B 和 B1 都下線的話, Redis 集群還是會停止運作。

Redis一致性保證

Redis 并不能保證數據的強一致性. 這意味這在實際中集群在特定的條件下可能會丟失寫操作:
第一個原因是因為集群是用了異步復制. 寫操作過程:

  1. 客戶端向主節點B寫入一條命令.
  2. 主節點B向客戶端回復命令狀態.
  3. 主節點將寫操作復制給他得從節點 B1, B2 和 B3

主節點對命令的復制工作發生在返回命令回復之后, 因為如果每次處理命令請求都需要等待復制操作完成的話, 那么主節點處理命令請求的速度將極大地降低 —— 我們必須在性能和一致性之間做出權衡。 注意:Redis 集群可能會在將來提供同步寫的方法。 Redis 集群另外一種可能會丟失命令的情況是集群出現了網絡分區, 并且一個客戶端與至少包括一個主節點在內的少數實例被孤立。
舉個例子 假設集群包含 A 、 B 、 C 、 A1 、 B1 、 C1 六個節點, 其中 A 、B 、C 為主節點, A1 、B1 、C1 為A,B,C的從節點, 還有一個客戶端 Z1 假設集群中發生網絡分區,那么集群可能會分為兩方,大部分的一方包含節點 A 、C 、A1 、B1 和 C1 ,小部分的一方則包含節點 B 和客戶端 Z1 .
Z1仍然能夠向主節點B中寫入, 如果網絡分區發生時間較短,那么集群將會繼續正常運作,如果分區的時間足夠讓大部分的一方將B1選舉為新的master,那么Z1寫入B中得數據便丟失了.
注意, 在網絡分裂出現期間, 客戶端 Z1 可以向主節點 B 發送寫命令的最大時間是有限制的, 這一時間限制稱為節點超時時間(node timeout), 是 Redis 集群的一個重要的配置選項

搭建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

安裝和啟動Redis

下載安裝包

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

解壓安裝

tar zxvf redis-3.2.9.tar.gz
cd redis-3.2.9
make && make PREFIX=/usr/local/redis install

這里如果失敗的自行yum安裝gcc和tcl

yum install gcc
yum install tcl

創建目錄

cd /usr/local/redis
mkdir cluster
cd cluster
mkdir 7000 7001 7002 7003 7004 7005

復制和修改配置文件

將redis目錄下的配置文件復制到對應端口文件夾下,6個文件夾都要復制一份

cp redis-3.2.9/redis.conf /usr/local/redis/cluster/7000

修改配置文件redis.conf,將下面的選項修改

# 端口號
port 7000
# 后臺啟動
daemonize yes
# 開啟集群
cluster-enabled yes
#集群節點配置文件
cluster-config-file nodes-7000.conf
# 集群連接超時時間
cluster-node-timeout 5000
# 進程pid的文件位置
pidfile /var/run/redis-7000.pid
# 開啟aof
appendonly yes
# aof文件路徑
appendfilename "appendonly-7005.aof"
# rdb文件路徑
dbfilename dump-7000.rdb

6個配置文件安裝對應的端口分別修改配置文件

創建啟動腳本

/usr/local/redis目錄下創建一個start.sh

#!/bin/bash
bin/redis-server cluster/7000/redis.conf
bin/redis-server cluster/7001/redis.conf
bin/redis-server cluster/7002/redis.conf
bin/redis-server cluster/7003/redis.conf
bin/redis-server cluster/7004/redis.conf
bin/redis-server cluster/7005/redis.conf

這個時候我們查看一下進程看啟動情況

ps -ef | grep redis

進程狀態如下:

root      1731     1  1 18:21 ?        00:00:49 bin/redis-server *:7000 [cluster]       
root      1733     1  0 18:21 ?        00:00:29 bin/redis-server *:7001 [cluster]       
root      1735     1  0 18:21 ?        00:00:08 bin/redis-server *:7002 [cluster]       
root      1743     1  0 18:21 ?        00:00:26 bin/redis-server *:7003 [cluster]       
root      1745     1  0 18:21 ?        00:00:13 bin/redis-server *:7004 [cluster]       
root      1749     1  0 18:21 ?        00:00:08 bin/redis-server *:7005 [cluster] 

有6個redis進程在開啟,說明我們的redis就啟動成功了

開啟集群

這里我們只是開啟了6個redis進程而已,它們都還只是獨立的狀態,還么有組成集群
這里我們使用官方提供的工具redis-trib,不過這個工具是用ruby寫的,要先安裝ruby的環境

yum install ruby rubygems -y

執行,報錯

[root@centos]# redis-trib.rb 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
/usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require': no such file to load -- redis (LoadError)
    from /usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `require'
    from /usr/local/bin/redis-trib.rb:25
[root@centos]#

原來是ruby和redis的連接沒安裝好
安裝gem-redis

gem install redis

安裝到這里的時候突然卡住很久不動,網上搜了下,這里需要翻墻或者換鏡像

gem source -a https://gems.ruby-china.org

這里可以將鏡像換成ruby-china的鏡像,不過我好像更換失敗,最終還是翻墻下載了

[root@centos]# gem install redis
Successfully installed redis-3.2.1
1 gem installed
Installing ri documentation for redis-3.2.1...
Installing RDoc documentation for redis-3.2.1...

等下載好后我們就可以使用了

[root@centos]# gem install redis
Successfully installed redis-3.2.1
1 gem installed
Installing ri documentation for redis-3.2.1...
Installing RDoc documentation for redis-3.2.1...

將redis-3.2.9的src目錄下的trib復制到相應文件夾

cp redis-3.2.9/src/redis-trib.rb /usr/local/redis/bin/redis-trib

創建集群:

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 就會將這份配置應用到集群當中:
>>> 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: bdcddddd3d78a866b44b68c7ae0e5ccf875c446a 127.0.0.1:7000
   slots:0-5460 (5461 slots) master
M: b85519795fa42aa33d4e88d25104cbae895933a6 127.0.0.1:7001
   slots:5461-10922 (5462 slots) master
M: b681e1a151890cbf957d1ff08352ee48f6ae39e6 127.0.0.1:7002
   slots:10923-16383 (5461 slots) master
S: d403713ab9db48aeac5b5393b69e1201026ef479 127.0.0.1:7003
   replicates bdcddddd3d78a866b44b68c7ae0e5ccf875c446a
S: b7ec92919e5bcffa76c8eee338f8ca5155293c64 127.0.0.1:7004
   replicates b85519795fa42aa33d4e88d25104cbae895933a6
S: 8a0d2a3f271b349744a971e1b0a545405de2742e 127.0.0.1:7005
   replicates b681e1a151890cbf957d1ff08352ee48f6ae39e6
Can I set the above configuration? (type 'yes' to accept):

按下yes,集群就會將配置應用到各個節點,并連接起(join)各個節點,也即是,讓各個節點開始通訊

>>> 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: bdcddddd3d78a866b44b68c7ae0e5ccf875c446a 127.0.0.1:7000
   slots:0-5460 (5461 slots) master
   1 additional replica(s)
S: d403713ab9db48aeac5b5393b69e1201026ef479 127.0.0.1:7003
   slots: (0 slots) slave
   replicates bdcddddd3d78a866b44b68c7ae0e5ccf875c446a
S: 8a0d2a3f271b349744a971e1b0a545405de2742e 127.0.0.1:7005
   slots: (0 slots) slave
   replicates b681e1a151890cbf957d1ff08352ee48f6ae39e6
M: b85519795fa42aa33d4e88d25104cbae895933a6 127.0.0.1:7001
   slots:5461-10922 (5462 slots) master
   1 additional replica(s)
S: b7ec92919e5bcffa76c8eee338f8ca5155293c64 127.0.0.1:7004
   slots: (0 slots) slave
   replicates b85519795fa42aa33d4e88d25104cbae895933a6
M: b681e1a151890cbf957d1ff08352ee48f6ae39e6 127.0.0.1:7002
   slots:10923-16383 (5461 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集群的使用

連接集群

這里我們使用reids-cli連接集群,使用時加上-c參數,就可以連接到集群
連接7000端口的節點

[root@centos1 redis]# ./redis-cli -c -p 7000
127.0.0.1:7000> set name zgj
-> Redirected to slot [5798] located at 127.0.0.1:7001
OK
127.0.0.1:7001> get name
"zgj"

前面的理論知識我們知道了,分配key的時候,它會使用CRC16算法,這里將keyname分配到了7001節點上

Redirected to slot [5798] located at 127.0.0.1:7001

redis cluster 采用的方式很直接,它直接跳轉到7001 節點了,而不是還在自身的7000節點。

好,現在我們連接7003這個從節點進入

[root@centos1 redis]# ./redis-cli -c -p 7003
127.0.0.1:7003> get name
-> Redirected to slot [5798] located at 127.0.0.1:7001
"zgj"

這里獲取name的值,也同樣跳轉到了7001上
我們再測試一下其他數據

127.0.0.1:7001> set age 20
-> Redirected to slot [741] located at 127.0.0.1:7000
OK
127.0.0.1:7000> set message helloworld
-> Redirected to slot [11537] located at 127.0.0.1:7002
OK
127.0.0.1:7002> set height 175
-> Redirected to slot [8223] located at 127.0.0.1:7001
OK

我們發現數據會在7000-7002這3個節點之間來回跳轉

測試集群中的節點掛掉

上面我們建立了一個集群,3個主節點和3個從節點,7000-7002負責存取數據,7003-7005負責把7000-7005的數據同步到自己的節點上來。
我們現在來模擬一下一臺matser服務器宕機的情況

[root@centos1 redis]# ps -ef | grep redis
root      1731     1  0 18:21 ?        00:01:02 bin/redis-server *:7000 [cluster]       
root      1733     1  0 18:21 ?        00:00:43 bin/redis-server *:7001 [cluster]       
root      1735     1  0 18:21 ?        00:00:22 bin/redis-server *:7002 [cluster]       
root      1743     1  0 18:21 ?        00:00:40 bin/redis-server *:7003 [cluster]       
root      1745     1  0 18:21 ?        00:00:27 bin/redis-server *:7004 [cluster]       
root      1749     1  0 18:21 ?        00:00:22 bin/redis-server *:7005 [cluster]       
root     23988     1  0 18:30 ?        00:00:42 ./redis-server *:6379    
root     24491  1635  0 21:55 pts/1    00:00:00 grep redis
[root@centos1 redis]# kill 1731
[root@centos1 redis]# bin/redis-trib check 127.0.0.1:7001
>>> Performing Cluster Check (using node 127.0.0.1:7001)
M: b85519795fa42aa33d4e88d25104cbae895933a6 127.0.0.1:7001
   slots:5461-10922 (5462 slots) master
   1 additional replica(s)
M: b681e1a151890cbf957d1ff08352ee48f6ae39e6 127.0.0.1:7002
   slots:10923-16383 (5461 slots) master
   1 additional replica(s)
S: b7ec92919e5bcffa76c8eee338f8ca5155293c64 127.0.0.1:7004
   slots: (0 slots) slave
   replicates b85519795fa42aa33d4e88d25104cbae895933a6
S: 8a0d2a3f271b349744a971e1b0a545405de2742e 127.0.0.1:7005
   slots: (0 slots) slave
   replicates b681e1a151890cbf957d1ff08352ee48f6ae39e6
M: d403713ab9db48aeac5b5393b69e1201026ef479 127.0.0.1:7003
   slots:0-5460 (5461 slots) master
   0 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.

這里看得出來,現在已經有了3個節點了,7003被選取成了替代7000成為主節點了。
我們再來模擬 7000節點重新啟動了的情況,那么它還會自動加入到集群中嗎?那么,7000這個節點上充當什么角色呢? 我們試一下:

[root@centos1 redis]# bin/redis-server cluster/7000/redis.conf
[root@centos1 redis]# bin/redis-trib check 127.0.0.1:7000
>>> Performing Cluster Check (using node 127.0.0.1:7000)
S: bdcddddd3d78a866b44b68c7ae0e5ccf875c446a 127.0.0.1:7000
   slots: (0 slots) slave
   replicates d403713ab9db48aeac5b5393b69e1201026ef479
S: b7ec92919e5bcffa76c8eee338f8ca5155293c64 127.0.0.1:7004
   slots: (0 slots) slave
   replicates b85519795fa42aa33d4e88d25104cbae895933a6
S: 8a0d2a3f271b349744a971e1b0a545405de2742e 127.0.0.1:7005
   slots: (0 slots) slave
   replicates b681e1a151890cbf957d1ff08352ee48f6ae39e6
M: b681e1a151890cbf957d1ff08352ee48f6ae39e6 127.0.0.1:7002
   slots:10923-16383 (5461 slots) master
   1 additional replica(s)
M: b85519795fa42aa33d4e88d25104cbae895933a6 127.0.0.1:7001
   slots:5461-10922 (5462 slots) master
   1 additional replica(s)
M: d403713ab9db48aeac5b5393b69e1201026ef479 127.0.0.1:7003
   slots:0-5460 (5461 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.

這里我們可以看到7000節點變成了7003節點的從節點
我們試著將7000和7003兩個節點都關掉

[root@centos1 redis]# ps -ef | grep redis
root      1733     1  0 18:21 ?        00:00:45 bin/redis-server *:7001 [cluster]       
root      1735     1  0 18:21 ?        00:00:24 bin/redis-server *:7002 [cluster]       
root      1743     1  0 18:21 ?        00:00:42 bin/redis-server *:7003 [cluster]       
root      1745     1  0 18:21 ?        00:00:29 bin/redis-server *:7004 [cluster]       
root      1749     1  0 18:21 ?        00:00:24 bin/redis-server *:7005 [cluster]       
root     23988     1  0 18:30 ?        00:00:43 ./redis-server *:6379    
root     24527     1  0 22:04 ?        00:00:00 bin/redis-server *:7000 [cluster]       
root     24541  1635  0 22:07 pts/1    00:00:00 grep redis
[root@centos1 redis] kill 1743
[root@centos1 redis] kill 24527

[root@centos1 redis]# bin/redis-trib check 127.0.0.1:7001
>>> Performing Cluster Check (using node 127.0.0.1:7001)
M: b85519795fa42aa33d4e88d25104cbae895933a6 127.0.0.1:7001
   slots:5461-10922 (5462 slots) master
   1 additional replica(s)
M: b681e1a151890cbf957d1ff08352ee48f6ae39e6 127.0.0.1:7002
   slots:10923-16383 (5461 slots) master
   1 additional replica(s)
S: b7ec92919e5bcffa76c8eee338f8ca5155293c64 127.0.0.1:7004
   slots: (0 slots) slave
   replicates b85519795fa42aa33d4e88d25104cbae895933a6
S: 8a0d2a3f271b349744a971e1b0a545405de2742e 127.0.0.1:7005
   slots: (0 slots) slave
   replicates b681e1a151890cbf957d1ff08352ee48f6ae39e6
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[ERR] Not all 16384 slots are covered by nodes.

這里我們的集群就不能工作了,因為兩個節點主節點和從節點都掛掉了,原來7001分配的slot現在無節點接管,需要人工介入重新分配slots。

集群中加入新的主節點

這里在cluster目錄下再新建一個7006并修改對應的配置文件,然后啟動這個這個redis進程
然后再使用redis-trib的add node指令加入節點

bin/redis-trib add-node 127.0.0.1:7006 127.0.0.1:7000

這里前面的節點表示要加入的節點,第二個節點表示要加入的集群中的任意一個節點,用來標識這個集群

[root@centos1 redis]# bin/redis-trib add-node 127.0.0.1:7006 127.0.0.1:7000
>>> Adding node 127.0.0.1:7006 to cluster 127.0.0.1:7000
>>> Performing Cluster Check (using node 127.0.0.1:7000)
M: bdcddddd3d78a866b44b68c7ae0e5ccf875c446a 127.0.0.1:7000
   slots:0-5460 (5461 slots) master
   1 additional replica(s)
S: d403713ab9db48aeac5b5393b69e1201026ef479 127.0.0.1:7003
   slots: (0 slots) slave
   replicates bdcddddd3d78a866b44b68c7ae0e5ccf875c446a
S: b7ec92919e5bcffa76c8eee338f8ca5155293c64 127.0.0.1:7004
   slots: (0 slots) slave
   replicates b85519795fa42aa33d4e88d25104cbae895933a6
M: b85519795fa42aa33d4e88d25104cbae895933a6 127.0.0.1:7001
   slots:5461-10922 (5462 slots) master
   1 additional replica(s)
S: 8a0d2a3f271b349744a971e1b0a545405de2742e 127.0.0.1:7005
   slots: (0 slots) slave
   replicates b681e1a151890cbf957d1ff08352ee48f6ae39e6
M: b681e1a151890cbf957d1ff08352ee48f6ae39e6 127.0.0.1:7002
   slots:10923-16383 (5461 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.
>>> Send CLUSTER MEET to node 127.0.0.1:7006 to make it join the cluster.
[OK] New node added correctly.
[root@centos1 redis]# bin/redis-trib check 127.0.0.1:7006
>>> Performing Cluster Check (using node 127.0.0.1:7000)
M: bdcddddd3d78a866b44b68c7ae0e5ccf875c446a 127.0.0.1:7000
   slots:0-5460 (5461 slots) master
   1 additional replica(s)
S: d403713ab9db48aeac5b5393b69e1201026ef479 127.0.0.1:7003
   slots: (0 slots) slave
   replicates bdcddddd3d78a866b44b68c7ae0e5ccf875c446a
S: b7ec92919e5bcffa76c8eee338f8ca5155293c64 127.0.0.1:7004
   slots: (0 slots) slave
   replicates b85519795fa42aa33d4e88d25104cbae895933a6
M: e55599320dabfb31bd22a01407e66121f075e7d3 127.0.0.1:7006
   slots: (0 slots) master
   0 additional replica(s)
M: b85519795fa42aa33d4e88d25104cbae895933a6 127.0.0.1:7001
   slots:5461-10922 (5462 slots) master
   1 additional replica(s)
S: 8a0d2a3f271b349744a971e1b0a545405de2742e 127.0.0.1:7005
   slots: (0 slots) slave
   replicates b681e1a151890cbf957d1ff08352ee48f6ae39e6
M: b681e1a151890cbf957d1ff08352ee48f6ae39e6 127.0.0.1:7002
   slots:10923-16383 (5461 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.

這里我們可以看到7006節點已經變成了一個主節點,然鵝,等等,好像發現了有什么地方不對

M: e55599320dabfb31bd22a01407e66121f075e7d3 127.0.0.1:7006
   slots: (0 slots) master

里面0 slots,也就是說節點6沒有分配哈希槽,即不能進行數據的存取,拿我加上去干嘛。。
原來redis cluster 不是在新加節點的時候幫我們做好了遷移工作,需要我們手動對集群進行重新分片遷移,也是這個命令:

/bin/redis-trib reshard 127.0.0.1:7000

這個命令是用來遷移slot節點的,后面的127.0.0.1:7000是表示哪個集群的,7000-7006都是可以的

[root@centos1]# redis-trib.rb reshard 127.0.0.1:7000
Connecting to node 127.0.0.1:7006: OK
Connecting to node 127.0.0.1:7001: OK
Connecting to node 127.0.0.1:7004: OK
Connecting to node 127.0.0.1:7000: OK
Connecting to node 127.0.0.1:7002: OK
Connecting to node 127.0.0.1:7005: OK
Connecting to node 127.0.0.1:7003: OK
>>> Performing Cluster Check (using node 127.0.0.1:7006)
M: efc3131fbdc6cf929720e0e0f7136cae85657481 127.0.0.1:7006
   slots: (0 slots) master
   0 additional replica(s)
M: cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c 127.0.0.1:7001
   slots:5461-10922 (5462 slots) master
   1 additional replica(s)
S: 4b4aef8b48c427a3c903518339d53b6447c58b93 127.0.0.1:7004
   slots: (0 slots) slave
   replicates cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c
S: 3707debcbe7be66d4a1968eaf3a5ffaf4308efa4 127.0.0.1:7000
   slots: (0 slots) slave
   replicates d2237fdcfbba672de766b913d1186cebcb6e1761
M: dfa0754c7854a874a6ebd2613b86140ad97701fc 127.0.0.1:7002
   slots:10923-16383 (5461 slots) master
   1 additional replica(s)
S: 30858dbf483b61b9838d5c1f853a60beaa4e7afd 127.0.0.1:7005
   slots: (0 slots) slave
   replicates dfa0754c7854a874a6ebd2613b86140ad97701fc
M: d2237fdcfbba672de766b913d1186cebcb6e1761 127.0.0.1:7003
   slots:0-5460 (5461 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.
How many slots do you want to move (from 1 to 16384)?

它提示我們需要遷移多少slot到7006上,我們可以算一下:16384/4 = 4096,也就是說,為了平衡分配起見,我們需要移動4096個槽點到7006上。

好,那輸入4096:
它又提示我們,接受的node ID是多少,7006的id 我們通過上面就可以看到是efc3131fbdc6cf929720e0e0f7136cae85657481:

What is the receiving node ID? efc3131fbdc6cf929720e0e0f7136cae85657481
Please enter all the source node IDs.
  Type 'all' to use all the nodes as source nodes for the hash slots.
  Type 'done' once you entered all the source nodes IDs.
Source node #1:

接著, redis-trib 會向你詢問重新分片的源節點(source node), 也即是, 要從哪個節點中取出 4096 個哈希槽, 并將這些槽移動到7006節點上面。

如果我們不打算從特定的節點上取出指定數量的哈希槽, 那么可以向 redis-trib 輸入 all , 這樣的話, 集群中的所有主節點都會成為源節點, redis-trib 將從各個源節點中各取出一部分哈希槽, 湊夠 4096 個, 然后移動到7006節點上:

Source node #1:all

接下來就開始遷移了,并且會詢問你是否確認:

Moving slot 1359 from d2237fdcfbba672de766b913d1186cebcb6e1761
    Moving slot 1360 from d2237fdcfbba672de766b913d1186cebcb6e1761
    Moving slot 1361 from d2237fdcfbba672de766b913d1186cebcb6e1761
    Moving slot 1362 from d2237fdcfbba672de766b913d1186cebcb6e1761
    Moving slot 1363 from d2237fdcfbba672de766b913d1186cebcb6e1761
    Moving slot 1364 from d2237fdcfbba672de766b913d1186cebcb6e1761
Do you want to proceed with the proposed reshard plan (yes/no)?

輸入yes并回車后,redis-trib就會正式執行重新分片操作,將制定的哈希槽從源節點一個個移動到7006節點上
遷移結束之后,我們來檢查一下

M: bdcddddd3d78a866b44b68c7ae0e5ccf875c446a 127.0.0.1:7000
   slots:1365-5460 (4096 slots) master
   1 additional replica(s)
S: d403713ab9db48aeac5b5393b69e1201026ef479 127.0.0.1:7003
   slots: (0 slots) slave
   replicates bdcddddd3d78a866b44b68c7ae0e5ccf875c446a
S: b7ec92919e5bcffa76c8eee338f8ca5155293c64 127.0.0.1:7004
   slots: (0 slots) slave
   replicates b85519795fa42aa33d4e88d25104cbae895933a6
M: e55599320dabfb31bd22a01407e66121f075e7d3 127.0.0.1:7006
   slots:0-1364,5461-6826,10923-12287 (4096 slots) master
   0 additional replica(s)
M: b85519795fa42aa33d4e88d25104cbae895933a6 127.0.0.1:7001
   slots:6827-10922 (4096 slots) master
   1 additional replica(s)
S: 8a0d2a3f271b349744a971e1b0a545405de2742e 127.0.0.1:7005
   slots: (0 slots) slave
   replicates b681e1a151890cbf957d1ff08352ee48f6ae39e6
M: b681e1a151890cbf957d1ff08352ee48f6ae39e6 127.0.0.1:7002
   slots:12288-16383 (4096 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.

我們可以看到
slots:0-1364,5461-6826,10923-12287 (4096 slots)
這些原來在其他節點上的哈希槽都遷移到了7006上

增加一個從節點

新建一個 7007從節點,作為7006的從節點

我們再新建一個節點7007,步驟類似,就先省略了。建好后,啟動起來,我們看如何把它加入到集群中的從節點中:

[root@centos1]# redis-trib.rb add-node --slave 127.0.0.1:7007 127.0.0.1:7000

add-node的時候加上--slave表示是加入到從節點中,但是這樣加,是隨機的。這里的命令行完全像我們在添加一個新主服務器時使用的一樣,所以我們沒有指定要給哪個主服 務器添加副本。這種情況下,redis-trib會將7007作為一個具有較少副本的隨機的主服務器的副本。

那么,你猜,它會作為誰的從節點,應該是7006,因為7006還沒有從節點。我們運行下。

[root@web3 7007]# redis-trib.rb add-node --slave 127.0.0.1:7007 127.0.0.1:7000
...
...
[OK] All 16384 slots covered.
Automatically selected master 127.0.0.1:7006
Connecting to node 127.0.0.1:7007: OK
>>> Send CLUSTER MEET to node 127.0.0.1:7007 to make it join the cluster.
Waiting for the cluster to join.
>>> Configure node as replica of 127.0.0.1:7006.
[OK] New node added correctly.

上面提示說,自動選擇了7006作為master節點。并且成功了。我們檢查下:

[root@centos1]# redis-trib.rb check 127.0.0.1:7000
Connecting to node 127.0.0.1:7000: OK
Connecting to node 127.0.0.1:7006: OK
Connecting to node 127.0.0.1:7004: OK
Connecting to node 127.0.0.1:7005: OK
Connecting to node 127.0.0.1:7003: OK
Connecting to node 127.0.0.1:7001: OK
Connecting to node 127.0.0.1:7007: OK
Connecting to node 127.0.0.1:7002: OK
>>> Performing Cluster Check (using node 127.0.0.1:7000)
S: 3707debcbe7be66d4a1968eaf3a5ffaf4308efa4 127.0.0.1:7000
   slots: (0 slots) slave
   replicates d2237fdcfbba672de766b913d1186cebcb6e1761
M: efc3131fbdc6cf929720e0e0f7136cae85657481 127.0.0.1:7006
   slots:0-1364,5461-6826,10923-12287 (4096 slots) master
   1 additional replica(s)
S: 4b4aef8b48c427a3c903518339d53b6447c58b93 127.0.0.1:7004
   slots: (0 slots) slave
   replicates cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c
S: 30858dbf483b61b9838d5c1f853a60beaa4e7afd 127.0.0.1:7005
   slots: (0 slots) slave
   replicates dfa0754c7854a874a6ebd2613b86140ad97701fc
M: d2237fdcfbba672de766b913d1186cebcb6e1761 127.0.0.1:7003
   slots:1365-5460 (4096 slots) master
   1 additional replica(s)
M: cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c 127.0.0.1:7001
   slots:6827-10922 (4096 slots) master
   1 additional replica(s)
S: 86d05e7c2b197dc182b5e71069e791d033cf899e 127.0.0.1:7007
   slots: (0 slots) slave
   replicates efc3131fbdc6cf929720e0e0f7136cae85657481
M: dfa0754c7854a874a6ebd2613b86140ad97701fc 127.0.0.1:7002
   slots:12288-16383 (4096 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.

果然,7007加入到了7006的從節點當中。

你說,我如果想指定一個主節點行不行?當然可以。我們再建一個7008節點。

bin/redis-trib.rb add-node --slave --master-id efc3131fbdc6cf929720e0e0f7136cae85657481 127.0.0.1:7008 127.0.0.1:7000

--master-id 表示指定的主節點node id。這里指定的是 7006 這個主節點。

Waiting for the cluster to join.
>>> Configure node as replica of 127.0.0.1:7006.
[OK] New node added correctly.

提示我們已經作為7006的從節點了,也就是加入到7006的從節點來了,照這么說,7006就有2個從節點了,我們看一下:

bin/redis-cli -c -p 7008 cluster nodes |grep efc3131fbdc6cf929720e0e0f7136cae85657481
86d05e7c2b197dc182b5e71069e791d033cf899e 127.0.0.1:7007 slave efc3131fbdc6cf929720e0e0f7136cae85657481 0 1445089507786 8 connected
efc3131fbdc6cf929720e0e0f7136cae85657481 127.0.0.1:7006 master - 0 1445089508289 8 connected 0-1364 5461-6826 10923-12287
44321e7d619410dc4e0a8745366610a0d06d2395 127.0.0.1:7008 myself,slave efc3131fbdc6cf929720e0e0f7136cae85657481 0 0 0 connected

我們過濾了下看結果,果真,7007和7008是7006的從節點了。

剛好,我們再做一個實驗,我把7006的進程殺掉,看7007和7008誰會變成主節點:

[root@centos1]# ps -ef|grep redis
root     11384     1  0 09:56 ?        00:00:16 redis-server *:7001 [cluster]
root     11388     1  0 09:56 ?        00:00:16 redis-server *:7002 [cluster]
root     11392     1  0 09:56 ?        00:00:16 redis-server *:7003 [cluster]
root     11396     1  0 09:56 ?        00:00:15 redis-server *:7004 [cluster]
root     11400     1  0 09:56 ?        00:00:15 redis-server *:7005 [cluster]
root     12100     1  0 11:01 ?        00:00:11 redis-server *:7000 [cluster]
root     12132     1  0 11:28 ?        00:00:11 redis-server *:7006 [cluster]
root     12202     1  0 13:14 ?        00:00:02 redis-server *:7007 [cluster]
root     12219     1  0 13:39 ?        00:00:00 redis-server *:7008 [cluster]
root     12239  8259  0 13:49 pts/0    00:00:00 grep redis
[root@centos1]# kill 12132
[root@centos1]# redis-cli -c -p 7008
127.0.0.1:7008> get ss5rtr
-> Redirected to slot [1188] located at 127.0.0.1:7007
"66"
127.0.0.1:7007> cluster nodes
efc3131fbdc6cf929720e0e0f7136cae85657481 127.0.0.1:7006 master,fail - 1445089780668 1445089779963 8 disconnected
d2237fdcfbba672de766b913d1186cebcb6e1761 127.0.0.1:7003 master - 0 1445089812195 7 connected 1365-5460
30858dbf483b61b9838d5c1f853a60beaa4e7afd 127.0.0.1:7005 slave dfa0754c7854a874a6ebd2613b86140ad97701fc 0 1445089813710 3 connected
86d05e7c2b197dc182b5e71069e791d033cf899e 127.0.0.1:7007 myself,master - 0 0 10 connected 0-1364 5461-6826 10923-12287
cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c 127.0.0.1:7001 master - 0 1445089814214 2 connected 6827-10922
4b4aef8b48c427a3c903518339d53b6447c58b93 127.0.0.1:7004 slave cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c 0 1445089812701 2 connected
44321e7d619410dc4e0a8745366610a0d06d2395 127.0.0.1:7008 slave 86d05e7c2b197dc182b5e71069e791d033cf899e 0 1445089814214 10 connected
3707debcbe7be66d4a1968eaf3a5ffaf4308efa4 127.0.0.1:7000 slave d2237fdcfbba672de766b913d1186cebcb6e1761 0 1445089813204 7 connected
dfa0754c7854a874a6ebd2613b86140ad97701fc 127.0.0.1:7002 master - 0 1445089813204 3 connected 12288-16383
127.0.0.1:7007>

這里7007獲得了成為主節點的機會,7008就變成了7007的從節點。

那么這個時候,重啟7006節點,那么他就會變成了一個7007的從節點了。

移除一個節點

上面是增加一個節點,接下來就是移除一個節點了,移除節點的命令是

bin/redis-trib del-node 127.0.0.1:7000 `<node-id>`

沒我們嘗試下輸入以下命令

[root@centos]# bin/redis-trib.rb del-node 127.0.0.1:7000 86d05e7c2b197dc182b5e71069e791d033cf899e
>>> Removing node 86d05e7c2b197dc182b5e71069e791d033cf899e from cluster 127.0.0.1:7000
Connecting to node 127.0.0.1:7000: OK
Connecting to node 127.0.0.1:7006: OK
Connecting to node 127.0.0.1:7004: OK
Connecting to node 127.0.0.1:7001: OK
Connecting to node 127.0.0.1:7003: OK
Connecting to node 127.0.0.1:7007: OK
Connecting to node 127.0.0.1:7008: OK
Connecting to node 127.0.0.1:7005: OK
Connecting to node 127.0.0.1:7002: OK
[ERR] Node 127.0.0.1:7007 is not empty! Reshard data away and try again.

這里報錯了,提示我們7007節點里面有數據,讓我們把7007節點里的數據移除出去,也就是說需要重新分片,這個和上面增加節點的方式一樣,我們再來一遍

bin/redis-trib.rb reshard 127.0.0.1:7000

省去中間內容,原來7007節點上已經有了4096個哈希槽,這里我們也移動4096個哈希槽
然后將這些哈希槽移動到7001節點上

Source node #1:86d05e7c2b197dc182b5e71069e791d033cf899e
Source node #2:done
Do you want to proceed with the proposed reshard plan (yes/no)? yes

然后我們再繼續執行移除命令,結果如下

[root@centos1]# redis-trib.rb del-node 127.0.0.1:7000 86d05e7c2b197dc182b5e71069e791d033cf899e
>>> Removing node 86d05e7c2b197dc182b5e71069e791d033cf899e from cluster 127.0.0.1:7000
Connecting to node 127.0.0.1:7000: OK
Connecting to node 127.0.0.1:7006: OK
Connecting to node 127.0.0.1:7004: OK
Connecting to node 127.0.0.1:7001: OK
Connecting to node 127.0.0.1:7003: OK
Connecting to node 127.0.0.1:7007: OK
Connecting to node 127.0.0.1:7008: OK
Connecting to node 127.0.0.1:7005: OK
Connecting to node 127.0.0.1:7002: OK
>>> Sending CLUSTER FORGET messages to the cluster...
>>> 127.0.0.1:7006 as replica of 127.0.0.1:7001
>>> 127.0.0.1:7008 as replica of 127.0.0.1:7001
>>> SHUTDOWN the node.

刪除成功,而且還很人性化的將7006和7008這2個原來7007的附屬節點送給了7001。考慮的真周到~

移除一個從節點

移除一個從節點就比較簡單了,因為從節點沒有哈希槽,也不需要考慮數據遷移,直接移除就行

[root@centos1]# redis-trib.rb del-node 127.0.0.1:7005 44321e7d619410dc4e0a8745366610a0d06d2395
>>> Removing node 44321e7d619410dc4e0a8745366610a0d06d2395 from cluster 127.0.0.1:7005
Connecting to node 127.0.0.1:7005: OK
Connecting to node 127.0.0.1:7001: OK
Connecting to node 127.0.0.1:7002: OK
Connecting to node 127.0.0.1:7004: OK
Connecting to node 127.0.0.1:7000: OK
Connecting to node 127.0.0.1:7006: OK
Connecting to node 127.0.0.1:7008: OK
Connecting to node 127.0.0.1:7003: OK
>>> Sending CLUSTER FORGET messages to the cluster...
>>> SHUTDOWN the node.
[root@centos1]# redis-trib.rb check 127.0.0.1:7008
Connecting to node 127.0.0.1:7008: [ERR] Sorry, can't connect to node 127.0.0.1:7008

表示移除成功

Redis性能測試

Redis自帶了性能測試工具redis-benchmark
使用說明如下:

Usage: redis-benchmark [-h <host>] [-p <port>] [-c <clients>] [-n <requests]> [-k <boolean>]

 -h <hostname>      Server hostname (default 127.0.0.1)
 -p <port>          Server port (default 6379)
 -s <socket>        Server socket (overrides host and port)
 -c <clients>       Number of parallel connections (default 50)
 -n <requests>      Total number of requests (default 10000)
 -d <size>          Data size of SET/GET value in bytes (default 2)
 -k <boolean>       1=keep alive 0=reconnect (default 1)
 -r <keyspacelen>   Use random keys for SET/GET/INCR, random values for SADD
  Using this option the benchmark will get/set keys
  in the form mykey_rand:000000012456 instead of constant
  keys, the <keyspacelen> argument determines the max
  number of values for the random number. For instance
  if set to 10 only rand:000000000000 - rand:000000000009
  range will be allowed.
 -P <numreq>        Pipeline <numreq> requests. Default 1 (no pipeline).
 -q                 Quiet. Just show query/sec values
 --csv              Output in CSV format
 -l                 Loop. Run the tests forever
 -t <tests>         Only run the comma-separated list of tests. The test
                    names are the same as the ones produced as output.
 -I                 Idle mode. Just open N idle connections and wait.

基準測試

基準的測試命令:
redis-benchmark -q -n 100000
結果入下:

root@centos1 bin]# redis-benchmark -q -n 100000
-bash: redis-benchmark: command not found
[root@centos1 bin]# ./redis-benchmark -q -n 100000
PING_INLINE: 61576.36 requests per second
PING_BULK: 60277.28 requests per second
SET: 61349.69 requests per second
GET: 60459.49 requests per second
INCR: 58858.15 requests per second
LPUSH: 59066.75 requests per second
RPUSH: 57339.45 requests per second
LPOP: 55586.44 requests per second
RPOP: 56465.27 requests per second
SADD: 57045.07 requests per second
SPOP: 53734.55 requests per second
LPUSH (needed to benchmark LRANGE): 57012.54 requests per second
LRANGE_100 (first 100 elements): 55803.57 requests per second
LRANGE_300 (first 300 elements): 54914.88 requests per second
LRANGE_500 (first 450 elements): 53333.33 requests per second
LRANGE_600 (first 600 elements): 56529.11 requests per second
MSET (10 keys): 59276.82 requests per second

這里可以看出,單機版的redis每秒可以處理6萬個請求,這已經是一個非常厲害的數據了,不得不佩服
我們再來看下集群情況下是是什么情況

[root@centos1 bin]# ./redis-benchmark -q -n 100000 -p 7000
PING_INLINE: 64599.48 requests per second
PING_BULK: 64184.85 requests per second
SET: 66800.27 requests per second
GET: 65616.80 requests per second
INCR: 66269.05 requests per second
LPUSH: 40273.86 requests per second
RPUSH: 40355.12 requests per second
LPOP: 43421.62 requests per second
RPOP: 45187.53 requests per second
SADD: 62539.09 requests per second
SPOP: 61538.46 requests per second
LPUSH (needed to benchmark LRANGE): 38182.51 requests per second
LRANGE_100 (first 100 elements): 25555.84 requests per second
LRANGE_300 (first 300 elements): 9571.21 requests per second
LRANGE_500 (first 450 elements): 7214.49 requests per second
LRANGE_600 (first 600 elements): 5478.85 requests per second
MSET (10 keys): 41893.59 requests per second

這里看出大部分和單機版的性能查不多,主要是lrange命令的差別是很大的

流水線測試

使用流水線
默認情況下,每個客戶端都是在一個請求完成之后才發送下一個請求(基準會模擬50個客戶端除非使用-c指定特別的數量),這意味著服務器幾乎是按順序讀取每個客戶端的命令。RTT也加入了其中。
真實世界會更復雜,Redis支持/topics/pipelining,使得可以一次性執行多條命令成為可能。Redis流水線可以提高服務器的TPS
redis-benchmark -n 1000000 -t set,get -P 16 -q 加入-P選項使用管道技術,一次執行多條命令

./redis-benchmark -n 1000000 -t set,get -P 16 -q
SET: 515198.34 requests per second
GET: 613873.56 requests per second

每秒處理get/sret請求達到了60/50W,真的厲害!

遇到的問題

  1. 安裝redis集群的時候遇到了挺多問題,踩了很多坑,單單是修改配置文件就出了不少問題,那些配置文件的內容都要一一修改,有些配置不修改就會出現無法創建進程的錯誤
  2. 注意配置集群的時候不要加密碼,否則會出現無法連接的情況
  3. gem install的時候需要修改鏡像或者翻墻
  4. 昨天啟動成功,今天啟動的時候報錯
[ERR] Node 172.168.63.202:7001 is not empty. Either the nodealready knows other nodes (check with CLUSTER NODES) or contains some key in database 0

解決方法:
1). 將需要新增的節點下aof、rdb等本地備份文件刪除;
2). 同時將新Node的集群配置文件刪除,即:刪除你redis.conf里面cluster-config-file所在的文件;
3). 再次添加新節點如果還是報錯,則登錄新Node,執行bin/redis-cli–h x –p對數據庫進行清除:

127.0.0.1:7001>  flushdb      #清空當前數據庫

總結

之間對了Redis的了解并不是說非常多,只是簡單的會用,因為現在企業里也很多都在用,剛好老大說接下來的項目可能會用到Redis集群,讓我先去了解下,所以最近就在回頭看,一邊看文檔,博客,一邊實踐,踩了很多的坑,出問題的時候的確是讓人感到很痛苦很郁悶的,可是當運行成功的那一刻心情卻是無比激動和開心的,可能這就是編程的魅力吧。

個人博客: http://blog.zgj12138.cn
CSDN: http://blog.csdn.net/zgj12138

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,488評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,034評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,327評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,554評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,337評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,883評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,975評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,114評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,625評論 1 332
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,555評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,737評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,244評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,973評論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,362評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,615評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,343評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,699評論 2 370

推薦閱讀更多精彩內容

  • 本文檔翻譯自 http://redis.io/topics/cluster-tutorial 。 本文檔是 Red...
    會跳舞的機器人閱讀 66,945評論 2 21
  • 轉自:https://www.zybuluo.com/phper/note/195558 前言 redis 是我們...
    yannhuang閱讀 1,696評論 0 2
  • 1 Redis介紹1.1 什么是NoSql為了解決高并發、高可擴展、高可用、大數據存儲問題而產生的數據庫解決方...
    克魯德李閱讀 5,329評論 0 36
  • 本文所有描述均為作者親自操作后總結出來的,如有疑問可直接留言,將及時回復,如本文理解或描述有誤的地...
    君哥聊編程閱讀 3,471評論 6 11
  • 失眠了...雖然不是第一次...但在學校還是頭一回...心里亂亂的...想找出頭緒卻一團亂麻...許是電影帶來的觸...
    南音_季閱讀 233評論 0 0