1. 程式人生 > 程式設計 >redis入門通識

redis入門通識

1.Redis初識

一. redis是什麼

Redis是一個開源的使用ANSI C語言編寫、支援網路、可基於記憶體亦可持久化的日誌型、Key-Value資料庫,並提供多種語言的API
複製程式碼

二.Redis的特性

1.速度快
官方給出 10w OPS/sec  每秒十萬次讀寫[操作])

原因:
	1.資料儲存於記憶體中(☆☆☆☆☆)
	2.C語言編寫,程式碼高效
	3.執行緒模型為單執行緒的(記憶體的執行緒 速度很快)
複製程式碼
2.持久化
redis的持久化是說redis在斷電的情況下可做到資料不丟失。
redis可以將記憶體資料通過RDB和AOF的方式寫入磁碟,從而達到持久化的效果。
(新版本支援RDB-AOF混合持久化)
複製程式碼
3.多種資料結構
string
hash 
list
set
sorted set
新增延伸資料結構以下(參考:http://www.redis.cn/topics/data-types-intro.html):
bitmaps:通過特殊的命令,你可以將 String 值當作一系列 bits 處理:可以設定和清除單獨的 bits,數出所有設為 1 的 bits 的數量,找到最前的被設為 1 或 0 的 bit,等等。(布隆過濾器)
HyperLogLogs: 這是被用於估計一個 set 中元素數量的概率性的資料結構。(唯一計數)
GEO:地理資訊定位(參考:https://www.jb51.net/article/136322.htm)
複製程式碼
4.支援多種語言
PHP
ActionScript
C
C++
C#
Clojure
Common Lisp
Dart
Erlang
Go
Haskell
Haxe
Io
Java
Node.js
Lua
Objective-C
Perl
Pure Data
Python
R
Ruby
Scala
Smalltalk
Tcl
複製程式碼
5.功能豐富
1.釋出訂閱
2.簡單事務
3.lua指令碼
4.pipeline
5.持久化
6.高可用
……
複製程式碼
7.主從複製
和MySQL主從複製的原因一樣,Redis雖然讀取寫入的速度都特別快,但是也會產生讀壓力特別大的情況。為了分擔讀壓力,Redis支援主從複製,Redis的主從結構可以採用一主多從或者級聯結構,Redis主從複製可以根據是否是全量分為全量同步和增量同步。
複製程式碼
8.高可用,分散式
高可用(High Availability),是當一臺伺服器停止服務後,對於業務及使用者毫無影響。 停止服務的原因可能由於網路卡、路由器、機房、CPU負載過高、記憶體溢位、自然災害等不可預期的原因導致,在很多時候也稱單點問題。

分散式(distributed),是當業務量、資料量增加時,可以通過任意增加減少伺服器數量來解決問題。

redis Sentinel --->高可用
redis Cluster  --->分散式
複製程式碼

Redis的典型使用場景

快取系統
計數器
訊息佇列系統
排行榜功能
適合社交網路
實時系統
布隆過濾器
複製程式碼

Redis的客戶端

我們使用的是PHP客戶端, Windows上可以使用Visual VMP來操作redis。

127.0.0.1:6379> ping
PONG
127.0.0.1:6379>
複製程式碼

除此之外我們可以在github下載Windows版本的msi安裝包,安裝完成後既可以使用。

https://github.com/MicrosoftArchive/redis/releases
複製程式碼

下載安裝後,我們先要啟動伺服器端。


C:\Redis>redis-server.exe  redis.windows.conf
                _._
           _.-``__ ''-._
      _.-``    `.  `_.  ''-._           Redis 3.2.100 (00000000/0) 64 bit
  .-`` .-```.  ```\/    _.,_ ''-._
 (    ',.-`  | `,)     Running in standalone mode
 |`-._`-...-` __...-.``-._|'` _.-'|     Port: 6379
 |    `-._   `._    /     _.-'    |     PID: 3692
  `-._    `-._  `-./  _.-'    _.-'
 |`-._`-._    `-.__.-'    _.-'_.-'|
 |    `-._`-._        _.-'_.-'    |           http://redis.io
  `-._    `-._`-.__.-'_.-'    _.-'
 |`-._`-._    `-.__.-'    _.-'_.-'|
 |    `-._`-._        _.-'_.-'    |
  `-._    `-._`-.__.-'_.-'    _.-'
      `-._    `-.__.-'    _.-'
          `-._        _.-'
              `-.__.-'

[3692] 13 Sep 17:37:48.676 # Server started,Redis version 3.2.100
複製程式碼

接著我們就可以啟動客服端了。

C:\Redis>redis-cli.exe -h 127.0.0.1 -p 6379
127.0.0.1:6379> ping
PONG
127.0.0.1:6379>
複製程式碼

這裡的埠是可以通過配置redis.windows.conf檔案修改的

redis的密碼設定

我們可以通過config set requirepass 密碼來設定redis的密碼 。

通過config get requirepass來獲取設定的密碼

tips:這裡設定密碼後如果重啟服務,密碼就會丟失

2.通用命令和資料結構

通用命令

keys redis資料庫中所有的鍵
127.0.0.1:6379> set name 'jim'
OK
127.0.0.1:6379> set age '18'
OK
127.0.0.1:6379> set project 'fullstack'
OK
127.0.0.1:6379> keys *
1) "project"
2) "name"
3) "age"
#keys 還可以進行正則的匹配
127.0.0.1:6379> keys n*  
1) "name"
127.0.0.1:6379>
複製程式碼
在實際線上環境,我們我們使用scan代替keys,keys掃描全庫,效率問題
dbsize 資料庫的大小
127.0.0.1:6379> dbsize
(integer) 3
127.0.0.1:6379> keys *
1) "name"
2) "age"
3) "project"
127.0.0.1:6379>
複製程式碼
exists key 判斷key是否存在
127.0.0.1:6379> exists name
(integer) 1
127.0.0.1:6379> exists hobby
(integer) 0
127.0.0.1:6379>
複製程式碼
del key 刪除key
127.0.0.1:6379> del age
(integer) 1
127.0.0.1:6379> keys *
1) "name"
2) "project"
127.0.0.1:6379>
複製程式碼
expire key seconds key的過期時間
127.0.0.1:6379> expire name 5
(integer) 1
127.0.0.1:6379> keys *
1) "project"
127.0.0.1:6379>
複製程式碼
擴充套件補充:我們可以使用ttl key檢視key的剩餘存活時間 如果是-2代表key不存在  persist key 去掉key的過期時間
127.0.0.1:6379> keys *
1) "project"
127.0.0.1:6379> expire project 60
(integer) 1
127.0.0.1:6379> ttl project
(integer) 51
127.0.0.1:6379> persist project
(integer) 1
127.0.0.1:6379> ttl project
(integer) -1
127.0.0.1:6379>
127.0.0.1:6379> ttl name
(integer) -2
複製程式碼
type key key的型別
127.0.0.1:6379> set face dilireba
OK
127.0.0.1:6379> type face
string
127.0.0.1:6379> sadd outlook beauty amazing
(integer) 2
127.0.0.1:6379> type outlook
set
127.0.0.1:6379> lpush height 170
(integer) 1
127.0.0.1:6379> type height
list
複製程式碼

擴充套件:type返回的資料有string,hash,list,set,zset,none

資料結構及內部編碼

img

字串型別的內部編碼有3種:

int:8個位元組的長整型。embstr:小於等於39個位元組的字串。raw:大於39個位元組的字串。

127.0.0.1:6379> object encoding face
"embstr"
127.0.0.1:6379> object encoding outlook
"hashtable"
複製程式碼

雜湊型別的內部編碼有兩種:

  • ziplist(壓縮列表):當雜湊型別元素個數小於hash-max-ziplist-entries配置(預設512個),

    同時所有值都小於hash-max-ziplist-value配置(預設64個位元組)時,Redis會使用ziplist作為雜湊的內部實現

    ziplist使用更加緊湊的結構實現多個元素的連續儲存,所以在節省記憶體方面比hashtable更加優秀。

  • hashtable(雜湊表):當雜湊型別無法滿足ziplist的條件時,Redis會使用hashtable作為雜湊的內部實現。

    因為此時ziplist的讀寫效率會下降,而hashtable的讀寫時間複雜度為O(1)。

當有value大於64個位元組,內部編碼會由ziplist變為hashtable:

127.0.0.1:6379> object encoding user:1
"ziplist"
127.0.0.1:6379> object encoding user:2
"hashtable"
127.0.0.1:6379>
複製程式碼

列表型別的內部編碼有兩種:

  • ziplist(壓縮列表):當雜湊型別元素個數小於hash-max-ziplist-entries配置(預設512個)

    同時所有值都小於hash-max-ziplist-value配置(預設64個位元組)時,Redis會使用ziplist作為雜湊的內部實現。

  • linkedlist(連結串列):當列表型別無法滿足ziplist的條件時,Redis會使用linkedlist作為列表的內部實現。

在3.2新版本中ziplist,linkedlist已經被quicklist取代

127.0.0.1:6379> object encoding height
"quicklist"
127.0.0.1:6379> lpush key1 1 2 3 4 5
(integer) 5
127.0.0.1:6379> object encoding key1
127.0.0.1:6379> lpush key2 1 2 3 4 5 6 7 8 9 11 12 12 12 12
1 1  1 1 1 1  1 11  11 1 1 1  1 1 1 1 1 1 1  11 1 1  11  1
 1 1 1 1  11 1  1 1 1 1 1  11  11  111  11 1  1 1 11 1  1
(integer) 137
127.0.0.1:6379> object encoding key2
"quicklist"
127.0.0.1:6379>

複製程式碼

集合型別的內部編碼有兩種:

  • intset(整數集合):當集合中的元素都是整數且元素個數小於set-max-intset-entries配置(預設512個)時,

    Redis會選用intset來作為集合內部實現,從而減少記憶體的使用。

  • hashtable(雜湊表):當集合型別無法滿足intset的條件時,Redis會使用hashtable作為集合的內部實現。

當元素個數較少時是intset,當元素個數超過512或者元素不為整數時內部編碼為hashtable

127.0.0.1:6379> sadd en 123 1231
(integer) 2
127.0.0.1:6379> object encoding en
"intset"
127.0.0.1:6379> sadd ao a b c 12 13
(integer) 5
127.0.0.1:6379> object encoding ao
"hashtable"
複製程式碼

有序集合型別的內部編碼有兩種

  • ziplist(壓縮列表):當有序集合的元素個數小於zset-max-ziplist-entries配置(預設128個)

    同時每個元素的值小於zset-max-ziplist-value配置(預設64個位元組)時,Redis會用ziplist來作為有序集合的內部實現,ziplist可以有效減少記憶體使用。

  • skiplist(跳躍表):當ziplist條件不滿足時,有序集合會使用skiplist作為內部實現,因為此時zip的讀寫效率會下降。

當元素較少時是ziplist,多於128時是skiplist

127.0.0.1:6379> zadd haode 12 a
(integer) 1
127.0.0.1:6379> zadd haode 12 12
(integer) 1
127.0.0.1:6379> zrange haode 0 -1
1) "12"
2) "a"
127.0.0.1:6379> object encoding haode
"ziplist"
複製程式碼

單執行緒架構

很多併發庫是多執行緒,但是redis是單執行緒,為什麼這麼快呢?
因為redis是純記憶體,
非阻塞IO,使用的epoll的模型
避免上下文切換和消耗競爭
複製程式碼

在有些時間使用的不僅僅是單執行緒,還有IO多路複用

3.Redis的持久化

Redis 提供了不同級別的持久化方式:

  • RDB持久化方式能夠在指定的時間間隔能對你的資料進行快照儲存.
  • AOF持久化方式記錄每次對伺服器寫的操作,當伺服器重啟的時候會重新執行這些命令來恢復原始的資料,AOF命令以redis協議追加儲存每次寫的操作到檔案末尾.Redis還能對AOF檔案進行後臺重寫,使得AOF檔案的體積不至於過大.
  • 如果你只希望你的資料在伺服器執行的時候存在,你也可以不使用任何持久化方式.
  • 你也可以同時開啟兩種持久化方式,在這種情況下,當redis重啟的時候會優先載入AOF檔案來恢復原始的資料,因為在通常情況下AOF檔案儲存的資料集要比RDB檔案儲存的資料集要完整.
  • 最重要的事情是瞭解RDB和AOF持久化方式的不同,讓我們以RDB持久化方式開始:

RDB方式

  • RDB是一個非常緊湊的檔案,它儲存了某個時間點得資料集,非常適用於資料集的備份,比如你可以在每個小時報儲存一下過去24小時內的資料,同時每天儲存過去30天的資料,這樣即使出了問題你也可以根據需求恢復到不同版本的資料集.
  • RDB是一個緊湊的單一檔案,很方便傳送到另一個遠端資料中心或者亞馬遜的S3(可能加密),非常適用於災難恢復.
  • RDB在儲存RDB檔案時父程式唯一需要做的就是fork出一個子程式,接下來的工作全部由子程式來做,父程式不需要再做其他IO操作,所以RDB持久化方式可以最大化redis的效能.
  • 與AOF相比,在恢復大的資料集的時候,RDB方式會更快一些.

redis預設的就是RDB方式的持久化方式

如果我們安裝的是單獨的redis則沒有使用持久化策略。

安裝visual-nmp預設的是RDB持久化,持久化的資料在安裝目錄的cache/redis/dump.rdb裡面。

save 900 1    900秒有一次改的就儲存
save 300 10	  300秒內有十次改的就儲存
save 60 10000 60秒內有10000次改的就儲存

# The filename where to dump the DB   rdb存放的檔名
dbfilename dump.rdb

# Redis to log on the standard output.
logfile "redis.log"  配置redis的日誌檔案
複製程式碼

AOF 方式

  • 使用AOF 會讓你的Redis更加耐久: 你可以使用不同的fsync策略:無fsync,每秒fsync,每次寫的時候fsync.使用預設的每秒fsync策略,Redis的效能依然很好(fsync是由後臺執行緒進行處理的,主執行緒會盡力處理客戶端請求),一旦出現故障,你最多丟失1秒的資料.
  • AOF檔案是一個只進行追加的日誌檔案,所以不需要寫入seek,即使由於某些原因(磁碟空間已滿,寫的過程中宕機等等)未執行完整的寫入命令,你也也可使用redis-check-aof工具修復這些問題.
  • Redis 可以在 AOF 檔案體積變得過大時,自動地在後臺對 AOF 進行重寫: 重寫後的新 AOF 檔案包含了恢復當前資料集所需的最小命令集合。 整個重寫操作是絕對安全的,因為 Redis 在建立新 AOF 檔案的過程中,會繼續將命令追加到現有的 AOF 檔案裡面,即使重寫過程中發生停機,現有的 AOF 檔案也不會丟失。 而一旦新 AOF 檔案建立完畢,Redis 就會從舊 AOF 檔案切換到新 AOF 檔案,並開始對新 AOF 檔案進行追加操作。
  • AOF 檔案有序地儲存了對資料庫執行的所有寫入操作, 這些寫入操作以 Redis 協議的格式儲存, 因此 AOF 檔案的內容非常容易被人讀懂, 對檔案進行分析(parse)也很輕鬆。 匯出(export) AOF 檔案也非常簡單: 舉個例子, 如果你不小心執行了 FLUSHALL 命令, 但只要 AOF 檔案未被重寫, 那麼只要停止伺服器, 移除 AOF 檔案末尾的 FLUSHALL 命令, 並重啟 Redis , 就可以將資料集恢復到 FLUSHALL 執行之前的狀態。
AOF的三種策略

always redis 的每條命令都從緩衝區寫到磁碟中

everysec redis每秒一次將命令從緩衝區寫到硬碟(預設值)

no redis根據系統決定是否將命令從緩衝區寫到硬碟

AOF實現的兩種方式
bgrewriteaof命令

要實現bgrewriteaof我們需要配置一下檔案

auto-aof-rewrite-percentage 100      檔案增長率(兩次的對比)
auto-aof-rewrite-min-size 64mb       自動重寫的最小尺寸
複製程式碼

aof重寫的相關統計項

aof_current_size   aof當前的檔案大小
aof_base_size      aof上次重寫或者啟動時的大小
複製程式碼

aof重寫同時滿足的條件

aof_current_size > auto-aof-rewrite-min-size
(aof_current_size - aof_base_size)/aof_base_size > auto-aof-rewrite-percentage
複製程式碼
aof重寫配置
appendonly no   是否重寫
appendfilename "appendonly.aof"  重寫的檔名
# appendfsync always
appendfsync everysec     預設的重寫策略
# appendfsync no
no-appendfsync-on-rewrite no  重寫的時候是否關鍵aof append
aof-load-truncated yes   重寫資料有錯誤是否忽略

複製程式碼
測試
127.0.0.1:6379> config get appendonly 檢視aof配置
1) "appendonly"
2) "no"
127.0.0.1:6379> config set appendonly yes
OK
127.0.0.1:6379> config rewrite
OK
127.0.0.1:6379> config get appendonly
1) "appendonly"
2) "yes"
127.0.0.1:6379>


複製程式碼

設定完成後,目錄生成appendonly.aof檔案,檔案內容如下。

……
SET
$4
name
$3
jim
*2
$6
SELECT
$1
0
*3
$3
set
$1
k
$5
hahah
……
複製程式碼

下面說下redis叢集的三種方式,分別是主從複製,Redis Sentinel (哨兵),redis-cluster。

4.Redis主從複製

redis中我們可以配置主從複製。

簡單的說就是一個master節點可以有多個slave節點,一個slave節點只能屬於一個master。資料是從master到slave的,就是說資料是單向的。

在redis中配置主從複製。

這裡也有兩種方式。

slaveof命令
配置檔案配置
複製程式碼

通過修改配置檔案實現主從複製。

1.修改配置檔案。如果是主節點的話,我們可以不需要修改配置。

2.修改slave節點

1.複製配置檔案 並重新命名
#修改內容如下
port 6380  埠號(☆☆☆☆☆)
logfile "redis6380.log"  redis log檔案
dbfilename "dump80.rdb"  rdb檔案
dir "C:\\Program Files\\Redis" 檔案路徑
slaveof 127.0.0.1 6379  從屬於哪個主節點(☆☆☆☆☆)
複製程式碼

測試

master伺服器端啟動

redis-server.exe redis.windows.slave.conf
複製程式碼

slave 伺服器端啟動

redis-server.exe redis.windows.slave.conf
複製程式碼

master 客服端啟動

redis-cli  #預設6379埠
複製程式碼

slave客戶端啟動

redis-cli.exe -p 6380
複製程式碼

master上寫資料

127.0.0.1:6379> set test thisisatest
OK
127.0.0.1:6379>
複製程式碼

slave上讀資料

127.0.0.1:6380> get test
"thisisatest"
127.0.0.1:6380>
複製程式碼

到此我們一個簡單測試就完成了。

如果我們在slave伺服器進行寫操作呢?

127.0.0.1:6380> set test11 testfromslave
(error) READONLY You can't write against a read only slave.
127.0.0.1:6380>

複製程式碼

master伺服器設定 slave-read-only yes 所以不能進行寫操作

tips 我們可以在master和slave上執行info     replication檢視主從情況

master

127.0.0.1:6379> info replication
# Replication
role:master   #角色是master
connected_slaves:1  #連線的slave 1臺
slave0:ip=127.0.0.1,port=6380,state=online,offset=751,lag=1
master_repl_offset:765
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:764
127.0.0.1:6379>
複製程式碼

slave

127.0.0.1:6380> info replication
# Replication
role:slave   #角色slave
master_host:127.0.0.1  #master的host
master_port:6379       #master的port
master_link_status:up
master_last_io_seconds_ago:4
master_sync_in_progress:0
slave_repl_offset:933
slave_priority:100
slave_read_only:1
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
127.0.0.1:6380>
複製程式碼

思考:如果master節點掛了,我們應該如何處理呢?

下面請看Redis Sentinel。

5.Redis Sentinel

作用:

用於管理多個Redis服務實現HA  1.監控主伺服器Master;  2.通知;  3.自動故障轉移;

協議:

流言協議、投票協議

工作過程

1)伺服器自身初始化,執行於redis-server中專用於sentinel功能的程式碼;

2)初始化sentinel狀態,根據給定的配置檔案,初始化監控的master伺服器列表;

3)建立連向master的連線;

配置主從

這裡我們配置了一主兩從的主從配置配置和前面的第四章節的主從配置一樣,這裡我們就不再演示。

配置sentinel

三個配置我們分別命名為sentinel12580.conf,sentinel12581.conf,sentinel12582.conf,配置項如下:

port 12580
sentinel monitor master 127.0.0.1 6379 2 
sentinel down-after-milliseconds master 5000
sentinel failover-timeout master 15000
複製程式碼

配置釋義

port 12580     #sentinel 埠
sentinel monitor master 127.0.0.1 6379 2 去監視一個名為mymaster的主redis例項,這個主例項的IP地址為本機地址127.0.0.1,埠號為6379,而將這個主例項判斷為失效至少需要2個 Sentinel程式的同意,只要同意Sentinel的數量不達標,自動failover就不會執行  
sentinel down-after-milliseconds master 5000
指定了Sentinel認為Redis例項已經失效所需的毫秒數。當 例項超過該時間沒有返回PING,或者直接返回錯誤,那麼Sentinel將這個例項標記為主觀下線。只有一個 Sentinel程式將例項標記為主觀下線並不一定會引起例項的自動故障遷移:只有在足夠數量的Sentinel都將一個例項標記為主觀下線之後,例項才會被標記為客觀下線,這時自動故障遷移才會執行  
sentinel failover-timeout master 15000

指定了在執行故障轉移時,最多可以有多少個從Redis例項在同步新的主例項,在從Redis例項較多的情況下這個數字越小,同步的時間越長,完成故障轉移所需的時間就越長  
複製程式碼

啟動主從伺服器

先啟動三個主從伺服器,啟動方式通第四章。啟動完成後,在master伺服器可以看到相關主從資訊。

[8312] 16 Sep 10:40:52.867 # Server started,Redis version 3.2.100
[8312] 16 Sep 10:40:52.870 * DB loaded from disk: 0.001 seconds
[8312] 16 Sep 10:40:52.872 * The server is now ready to accept connections on port 6379
[8312] 16 Sep 10:40:53.188 * Slave 127.0.0.1:6381 asks for synchronization
[8312] 16 Sep 10:40:53.190 * Partial resynchronization not accepted: Runid mismatch (Client asked for runid '36a72ab0752754f28ba5db09d0
231dada9f9dca5',my runid is 'ccd2050bf885d9cf90b3942b4090235d68e02443')
[8312] 16 Sep 10:40:53.193 * Starting BGSAVE for SYNC with target: disk
[8312] 16 Sep 10:40:53.234 * Background saving started by pid 4080
[8312] 16 Sep 10:40:53.256 * Slave 127.0.0.1:6380 asks for synchronization
[8312] 16 Sep 10:40:53.259 * Partial resynchronization not accepted: Runid mismatch (Client asked for runid '36a72ab0752754f28ba5db09d0
231dada9f9dca5',my runid is 'ccd2050bf885d9cf90b3942b4090235d68e02443')
[8312] 16 Sep 10:40:53.263 * Waiting for end of BGSAVE for SYNC
[8312] 16 Sep 10:40:53.375 # fork operation complete
[8312] 16 Sep 10:40:53.378 * Background saving terminated with success
[8312] 16 Sep 10:40:53.388 * Synchronization with slave 127.0.0.1:6381 succeeded
[8312] 16 Sep 10:40:53.393 * Synchronization with slave 127.0.0.1:6380 succeeded
複製程式碼

啟動Redis Sentinel

啟動方式是依次使用redis-cli.exe sentinel12580.conf,redis-cli.exe sentinel12581.conf,redis-cli.exe sentinel12582.conf

C:\Program Files\Redis>redis-server.exe sentinel12580.conf
[1040] 14 Sep 10:44:54.281 #
*** FATAL CONFIG FILE ERROR ***

[1040] 16 Sep 10:44:54.283 # Reading the configuration file,at line 2

[1040] 16 Sep 10:44:54.283 # >>> 'sentinel myid 367e595d569bb8d30a0c2c96c2d5f5ff4ffbde7d'

[1040] 16 Sep 10:44:54.283 # sentinel directive while not in sentinel mode
複製程式碼

啟動完成報了以上的錯,是因為我們沒有使用sentinel模式,只需要配置檔案後面加上 --sentinel即可

C:\Program Files\Redis>redis-server.exe sentinel12580.conf --sentinel
                _._
           _.-``__ ''-._
      _.-``    `.  `_.  ''-._           Redis 3.2.100 (00000000/0) 64 bit
  .-`` .-```.  ```\/    _.,_ ''-._
 (    ',)     Running in sentinel mode
 |`-._`-...-` __...-.``-._|'` _.-'|     Port: 12580
 |    `-._   `._    /     _.-'    |     PID: 8320
  `-._    `-._  `-./  _.-'    _.-'
 |`-._`-._    `-.__.-'    _.-'_.-'|
 |    `-._`-._        _.-'_.-'    |           http://redis.io
  `-._    `-._`-.__.-'_.-'    _.-'
 |`-._`-._    `-.__.-'    _.-'_.-'|
 |    `-._`-._        _.-'_.-'    |
  `-._    `-._`-.__.-'_.-'    _.-'
      `-._    `-.__.-'    _.-'
          `-._        _.-'
              `-.__.-'

[8320] 16 Sep 10:46:59.725 # Sentinel ID is 367e595d569bb8d30a0c2c96c2d5f5ff4ffbde7d
[8320] 16 Sep 10:46:59.726 # +monitor master master 127.0.0.1 6379 quorum 2
[8320] 16 Sep 10:47:04.768 # +sdown sentinel 4867b5b8d310a25fd8d05e5fef2377deddefbb08 127.0.0.1 12582 @ master 127.0.0.1 6379
[8320] 16 Sep 10:47:04.769 # +sdown sentinel 3bea1b075787ab7b7bbe55d728f7ad68f0cffba5 127.0.0.1 12581 @ master 127.0.0.1 6379
複製程式碼

出現以上內容,這說明我們的Redis Sentinel啟動成功

啟動成功後,我們可以看到redis sentinel在監控master節點了

[8320] 16 Sep 10:46:59.726 # +monitor master master 127.0.0.1 6379 quorum 2
複製程式碼

測試

首先退出master節點
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=127.0.0.1,port=6381,offset=52880,lag=1
slave1:ip=127.0.0.1,lag=0
master_repl_offset:52880
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:52879
127.0.0.1:6379> shutdown
not connected> exit

C:\Program Files\Redis>
複製程式碼
主節點已經關閉
[8312] 16 Sep 10:40:53.263 * Waiting for end of BGSAVE for SYNC
[8312] 16 Sep 10:40:53.375 # fork operation complete
[8312] 16 Sep 10:40:53.378 * Background saving terminated with success
[8312] 16 Sep 10:40:53.388 * Synchronization with slave 127.0.0.1:6381 succeeded
[8312] 16 Sep 10:40:53.393 * Synchronization with slave 127.0.0.1:6380 succeeded
[8312] 16 Sep 10:52:43.850 # User requested shutdown...
[8312] 16 Sep 10:52:43.850 * Saving the final RDB snapshot before exiting.
[8312] 16 Sep 10:52:43.855 * DB saved on disk
[8312] 14 Sep 10:52:43.855 # Redis is now ready to exit,bye bye...
複製程式碼
檢視Redis Sentinel的資訊提示
Sep 10:52:58.611 # +switch-master master 127.0.0.1 6379 127.0.0.1 6380  已經切換成功
Sep 10:52:58.618 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ master 127.0.0.1 6380
Sep 10:52:58.629 * +slave slave 127.0.0.1:6379 127.0.0.1 6379 @ master 127.0.0.1 6380
Sep 10:53:03.633 # +sdown slave 127.0.0.1:6379 127.0.0.1 6379 @ master 127.0.0.1 6380
Sep 10:53:03.633 # +sdown slave 127.0.0.1:6381 127.0.0.1 6381 @ master 127.0.0.1 6380
Sep 10:53:31.594 # -sdown slave 127.0.0.1:6381 127.0.0.1 6381 @ master 127.0.0.1 6380
複製程式碼

當我們再次啟動主節點的時候會自動切換回6379主節點

Sep 10:59:17.920 # +switch-master master 127.0.0.1 6381 127.0.0.1 6379
Sep 10:59:17.925 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ master 127.0.0.1 6379
Sep 10:59:17.927 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ master 127.0.0.1 6379
Sep 10:59:22.985 # +sdown slave 127.0.0.1:6381 127.0.0.1 6381 @ master 127.0.0.1 6379
Sep 10:59:22.986 # +sdown slave 127.0.0.1:6380 127.0.0.1 6380 @ master 127.0.0.1 6379
Sep 10:59:38.185 # -sdown slave 127.0.0.1:6381 127.0.0.1 6381 @ master 127.0.0.1 6379
Sep 10:59:38.186 # -sdown slave 127.0.0.1:6380 127.0.0.1 6380 @ master 127.0.0.1 6379
複製程式碼

到此Redis Sentinel基本使用應經講解完成。

6.Redis Cluster

介紹

Redis Cluster是Redis的分散式解決方案,在Redis 3.0版本正式推出的,有效解決了Redis分散式方面的需求。當遇到單機記憶體、併發、流量等瓶頸時,可以採用Cluster架構達到負載均衡的目的。
複製程式碼

資料分佈

分散式資料庫首要解決把整個資料集按照分割槽規則對映到多個節點的問題,即把資料集劃分到多個節點上,每個節點負責整個資料的一個子集。常見的分割槽規則有雜湊分割槽和順序分割槽。Redis Cluster採用雜湊分割槽規則,因此接下來會討論雜湊分割槽規則。常見的雜湊分割槽有以下幾種:

節點取餘分割槽 一致性雜湊分割槽 虛擬槽分割槽

Redis Cluster採用虛擬槽分割槽,因此先介紹一下虛擬槽分割槽。

虛擬槽分割槽巧妙地使用了雜湊空間,使用分散度良好的雜湊函式把所有的資料對映到一個固定範圍內的整數集合,整數定義為槽(slot)。比如Redis Cluster槽的範圍是0 ~ 16383。槽是叢集內資料管理和遷移的基本單位。採用大範圍的槽的主要目的是為了方便資料的拆分和叢集的擴充套件,每個節點負責一定數量的槽。

redis-cluster

redis-cluster的優勢  

  1、官方推薦,毋庸置疑。

  2、去中心化,叢集最大可增加1000個節點,效能隨節點增加而線性擴充套件。

  3、管理方便,後續可自行增加或摘除節點,移動分槽等等。

  4、簡單,易上手。

redis-cluster 配置

首先配置新建cluster配置檔案分別為cluster-7000.conf,cluster-7001.conf,……cluster-7005.conf六個節點。

基本配置檔案如下:

port  7000         //埠
daemonize    yes            //redis後臺執行  
cluster-enabled yes        //開啟cluster
logfile "7005.log"      //日誌檔案
dbfilename "7005.rdb"    //rdb檔案
cluster-config-file  nodes.conf   //叢集的配置  配置檔案首次啟動自動生成 7000,7001,7002
cluster-node-timeout  15000      //請求超時  預設15秒,可自行設定
appendonly  yes             //aof日誌開啟  有需要就開啟,它會每次寫操作都記錄一條日誌 
複製程式碼

啟動redis-cluster

依次啟動各個節點,示例如下。

redis-server.exe cluster-7000.conf
複製程式碼

啟動節點之後,我們進行連線測試。

>redis-cli.exe -p 7000
127.0.0.1:7000> set name katy
(error) CLUSTERDOWN The cluster is down
127.0.0.1:7000>
複製程式碼

這裡出現了(error) CLUSTERDOWN The cluster is down這是提示當前叢集不可用,因為redis採用虛擬槽分割槽,這裡的16384個槽沒有進行分配所以報錯。

我們也可以檢視當前節點的資訊。

127.0.0.1:7000> cluster info
cluster_state:fail
cluster_slots_assigned:0
cluster_slots_ok:0
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:1
cluster_size:1
cluster_current_epoch:0
cluster_my_epoch:0
cluster_stats_messages_sent:0
cluster_stats_messages_received:0
複製程式碼

通過上面資訊我們可以看到,當前節點的狀態為fail.分配槽和成功的槽均為0.

節點的握手meet

我們需要執行cluster meet 讓各個節點通訊,握手。

>redis-cli.exe -p 7000 cluster meet 127.0.0.1 7001
OK
……
複製程式碼

出現ok,代表我們已經成功握手通訊。

我們再次執行cluster nodes 檢視節點資訊

>redis-cli -p 7000 cluster nodes
ac7619753c43403709289c1be62b43c20ffced4f 127.0.0.1:7004 master - 0 1537169481099 4 connected
ac182f675425888fa38f62d0e40b8020a6d3d6af 127.0.0.1:7002 master - 0 1537169483120 3 connected
065c4745c983e3e7ddf0d7dfc608bcfdda451523 127.0.0.1:7005 master - 0 1537169481603 5 connected
3d0ca5303f8896579b1bc9f7968fb0bb20a1b261 127.0.0.1:7000 myself,master - 0 0 1 connected
8ae5e70ecbf33809d5845702798493f2dccd511b 127.0.0.1:7003 master - 0 1537169482110 2 connected
f419fc0c82702bfe5606eda89ae31a19a531eb06 127.0.0.1:7001 master - 0 1537169484130 0 connected
複製程式碼

應經成功連線。

我們檢視節點資訊已經出現了6個。

>redis-cli.exe -p 7000 cluster info
cluster_state:fail
cluster_slots_assigned:0
cluster_slots_ok:0
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:0
cluster_current_epoch:5
cluster_my_epoch:1
cluster_stats_messages_sent:991
cluster_stats_messages_received:991


複製程式碼

啟動主從

我們這裡將7000,7002節點設定為主節點,7003,7004,7005為從節點,對應關係是7003節點複製7000資料,7004節點複製7001資料,7005節點複製7002資料。使用的命令是:

redis-cli.exe -p 7003 cluster replicate 節點node
複製程式碼

再次檢視節點info

127.0.0.1:7000> cluster info
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:5
cluster_my_epoch:1
cluster_stats_messages_sent:6197
cluster_stats_messages_received:6197
複製程式碼

檢視節點

>redis-cli -p 7000 cluster nodes
ac7619753c43403709289c1be62b43c20ffced4f 127.0.0.1:7004 slave f419fc0c82702bfe5606eda89ae31a19a531eb06 0 1537172093492 4 connected
ac182f675425888fa38f62d0e40b8020a6d3d6af 127.0.0.1:7002 slave 3d0ca5303f8896579b1bc9f7968fb0bb20a1b261 0 1537172096536 3 connected
065c4745c983e3e7ddf0d7dfc608bcfdda451523 127.0.0.1:7005 master - 0 1537172092377 5 connected 5462-10922
3d0ca5303f8896579b1bc9f7968fb0bb20a1b261 127.0.0.1:7000 myself,master - 0 0 1 connected 0-5461
8ae5e70ecbf33809d5845702798493f2dccd511b 127.0.0.1:7003 slave 065c4745c983e3e7ddf0d7dfc608bcfdda451523 0 1537172095523 5 connected
f419fc0c82702bfe5606eda89ae31a19a531eb06 127.0.0.1:7001 master - 0 1537172094513 0 connected 10923-16383
複製程式碼

這裡可以看到已經是三個master節點,三個slave節點

我們還可以使用cluster slots檢視槽位的分配資訊。

/redis# redis-cli -p 7000 cluster slots
1) 1) (integer) 5462
   2) (integer) 10922
   3) 1) "127.0.0.1"
      2) (integer) 7005
   4) 1) "127.0.0.1"
      2) (integer) 7003
2) 1) (integer) 0
   2) (integer) 5461
   3) 1) "127.0.0.1"
      2) (integer) 7000
   4) 1) "127.0.0.1"
      2) (integer) 7002
3) 1) (integer) 10923
   2) (integer) 16383
   3) 1) "127.0.0.1"
      2) (integer) 7001
   4) 1) "127.0.0.1"
      2) (integer) 7004
複製程式碼

現在我們測試讀寫操作。

127.0.0.1:7000> set hello world
OK
127.0.0.1:7000> get hello 
"world"
127.0.0.1:7000> set key keys
(error) MOVED 12539 127.0.0.1:7001
複製程式碼

這裡出現了一個MOVED錯誤,是因為7000節點的槽分配為0-5462,但設定key時的槽位12539,所以出現了一個MOVED的錯誤。

我們可以在啟動服務是使用redis-cli -c -p 7000命令來啟動服務。

/etc/redis# redis-cli -c -p 7000
127.0.0.1:7000> set key keys
-> Redirected to slot [12539] located at 127.0.0.1:7001
OK
127.0.0.1:7001> 
複製程式碼

這時系統會自動重定向到7001節點12539這個槽。

測試自動切換master

我們此時殺死一個master 7000,此時再看。

 ps -ef |grep redis
redis      7358      1  0 15:09 ?        00:00:11 /usr/bin/redis-server 127.0.0.1:6379
root       8212   2342  0 15:23 ?        00:00:16 redis-server *:7001 [cluster]
root       8230   2342  0 15:23 ?        00:00:11 redis-server *:7002 [cluster]
root       8248   2342  0 15:23 ?        00:00:11 redis-server *:7003 [cluster]
root       8266   2342  0 15:23 ?        00:00:11 redis-server *:7004 [cluster]
root      31475      1  0 16:46 ?        00:00:00 redis-server *:7005 [cluster]
複製程式碼

檢視節點資訊

redis-cli -p 7001 cluster nodes
redis-cli -p 7001 cluster nodes
3d0ca5303f8896579b1bc9f7968fb0bb20a1b261 127.0.0.1:7000 master,fail - 1537174104941 1537174099583 1 disconnected
065c4745c983e3e7ddf0d7dfc608bcfdda451523 127.0.0.1:7005 slave 8ae5e70ecbf33809d5845702798493f2dccd511b 0 1537174159373 6 connected
ac7619753c43403709289c1be62b43c20ffced4f 127.0.0.1:7004 slave f419fc0c82702bfe5606eda89ae31a19a531eb06 0 1537174157348 4 connected
f419fc0c82702bfe5606eda89ae31a19a531eb06 127.0.0.1:7001 myself,master - 0 0 0 connected 10923-16383
8ae5e70ecbf33809d5845702798493f2dccd511b 127.0.0.1:7003 master - 0 1537174155317 6 connected 5462-10922
ac182f675425888fa38f62d0e40b8020a6d3d6af 127.0.0.1:7002 master - 0 1537174158361 7 connected 0-5461
複製程式碼

此時7000這個master已經掛了,但是7003自動升級成master了。

7000節點已經掛了,那此時的7000節點的資料呢?我們可以檢視下。

 redis-cli -p 7001 -c
127.0.0.1:7001> keys *
1) "name1"
2) "key"
3) "name5"
127.0.0.1:7001> get hello
-> Redirected to slot [866] located at 127.0.0.1:7002
"world"
複製程式碼

原來在7000上的hello 已經重定向7002節點上了。

PHP連線redis-cluster叢集

 require 'predis/autoload.php';//引入predis相關包  
    //redis例項  
    $servers = array(  
        'tcp://192.168.1.198:7000','tcp://192.168.1.198:7001','tcp://192.168.1.198:7002','tcp://192.168.1.199:7003','tcp://192.168.1.199:7004','tcp://192.168.1.199:7005',);  
      
    $client = new Predis\Client($servers,array('cluster' => 'redis'));  
      
    $client->set("name1","jim");  
    $client->set("name2","tom");  
    $client->set("name3","lucy");  
      
    $name1 = $client->get('name1');  
    $name2 = $client->get('name2');  
    $name3 = $client->get('name3');  

複製程式碼

這裡可以使用predis擴充套件操作redis-cluster叢集。end……