redis簡介
Redis單純程模型,支持主從模式,提高可用性,是一個開源項目,經常用來當一個數據結構服務器。其是內存級別的緩存服務器並可實現持久化功能. 據稱一百萬的變量存儲(字串)佔用100M內存空間,單臺redis服務器可達到5萬併發的能力。
redis與memcache的對比
redis的優勢
- 支持豐富的操作
- 主從複製和集羣
- 就地更新操作
- 支持持久化(磁盤),避免雪崩效應
memcache優勢
- 多線程,善用多核CPU,更少的阻塞操作
- 更少的內存開銷
- 更少的內存分配壓力
- 可能有更少的內存碎片
redis的組件
redis的工作端口
-
6379/TCP
redis-cli命令的參數
-
-h HOST
: 連接的主機地址或主機名 -
-p PORT
:連接的端口 -
-s socket
: 指定套接字 -
-a password
: 指定連接密碼 -
-r <repeat>
: 指定命令運行多次
redis-cli中相關的命令
-
connection相關的命令
-
auth PASS
: 認證 -
ping
: 測試服務器是否在線 -
echo "string"
: 顯示string -
quit
: 退出 -
select #
: 挑選指定的名稱空間(即數據庫) -
help @connection
: 獲取與連接相關的命令幫助
-
-
與服務器端支持的命令
-
help @server
: 獲取與服務器端相關的命令幫助 -
bgsave
: 實現異步將數據集同步到磁盤上 -
client getname
: 獲取當前客戶端的連接名 -
client kill IP:PORT
: 指定IP:PORT可關閉相關的連接信息 -
client list
: 查看客戶端的連接信息172.16.36.70:6379> client list id=5 addr=172.16.36.70:57606 fd=8 name= age=904 idle=879 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=get
-
client setname CONNECTION-NAME
: 設定當前連接的名稱 -
info
: 查看當前服務器的狀態信息 -
info memory
: 只顯示memory段的相關信息 -
config resetstart
: 重置info中所統計的數據 -
config set PARAMETER value
: 運行時修改設定指定參數的值,只保存在內存中 -
config rewrite
: 將修改在內存中的參數值同步到配置文件中 -
config get dir
: 查看redis的文件保存目錄 -
dbsize
: 顯示數據庫中所有鍵的數量 -
lastsave
: 用來獲取最新一次save執行的時間戳 -
save
: 保存數據到磁盤 -
monitor
: 實時監控所接收到的請求 -
shutdown
: 將所有數據從內存同步到磁盤,並安全關閉 -
shutdown [nosave][save]
: 關閉程序並選擇是否將數據同步到磁盤上 -
salveof HOST PORT
:配置主從,當前節點將變成從節點 -
slowlog
: 查看慢查詢日誌,需要開啓慢查詢日誌功能 -
sync
: 複製功能的內建命令
-
-
與訂閱相關的命令
-
help @pubsub
: 獲取與訂閱相關的命令 -
psubscribe
: 基於模式進行訂閱 -
publish
: 向頻道發送消息 -
subscribe CHANNEL
: 訂閱一個頻道
-
redis的認證功能
vim /etc/redis.conf
requirepass zhenping.com
重啓redis服務
systemctl restart redis
連接redis並認證的方法
redis-cli -h 172.16.36.70
172.16.36.70:6379> select 0
(error) NOAUTH Authentication required.
172.16.36.70:6379> auth zhenping
OK
redis清空數據庫
-
flushdb
: 清空當前庫 -
flushall
: 清空所有庫[root@Centos7 ~]# redis-cli -h 172.16.36.70 172.16.36.70:6379> flushall OK 172.16.36.70:6379> flushdb OK
redis的事務功能
通過multi
,exec
,watch
等命令來實現事務功能,將多個命令打包,多個命令按順序執行,並一次執行完成,並將執行結果一次性全部返回給客戶端。redis事務不支持回滾操作,在事務中應避免發生錯誤(如命令寫錯等),事務了也將會執行失敗。
-
multi
: 啓動一個事務 -
exec
: 執行事務,一次性將事務中的所有操作執行完成後,返回給客戶端 -
watch
: 樂觀鎖機制,在EXEC命令執行之前 ,用於監視指定數據鍵,如果監視的某任意鍵數據被修改,服務器拒絕執行事務
####建立一個事務
[root@Centos7 ~]# redis-cli -h 172.16.36.70
172.16.36.70:6379> multi
OK
172.16.36.70:6379> set ip 172.16.36.70
QUEUED
172.16.36.70:6379> get ip
QUEUED
172.16.36.70:6379> set prot 8080
QUEUED
172.16.36.70:6379> exec
1) OK
2) "172.16.36.70"
3) OK
####使用watch機制監控鍵
[root@Centos7 ~]# redis-cli -h 172.16.36.70
172.16.36.70:6379> watch ip
OK
172.16.36.70:6379> multi
OK
172.16.36.70:6379> set ip 172.16.36.71
QUEUED
172.16.36.70:6379> get ip
QUEUED
172.16.36.70:6379> exec
(nil)
說明: 當watch ip指令發出後,其它的請求操作改變了IP鍵的值,此時新發起的事務中,如果也要改變其值, 此事務申請將會失敗
redis的發佈和訂閱功能(publish/subscribe)
發佈和訂閱功能被廣泛用於構建即時通信應用,比如:網絡聊天室和實時廣播、實時提醒等。 訂閱發佈功能就能幫你很輕鬆地實現通知、監控程序
-
subsciribe CHANNEL_NAME
: 訂閱一個頻道 -
publish CHANNEL_NAME
: 向頻道發送一個消息 -
unsubscribe CHANNEL_NAME
: 退訂頻道 -
psubscribe CHANNEL_NAME_PATTERN
: 基於正則表達式模式定義多個頻道
1、訂閱一個頻道:
72.16.36.70:6379> subscribe news
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "news"
3) (integer) 1
2、向頻道發送消息
172.16.36.70:6379> publish news weizhenping
(integer) 1
3、頻道會接收下來消息
[root@Centos7 ~]# redis-cli -h 172.16.36.70
172.16.36.70:6379> subscribe news
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "news"
3) (integer) 1
1) "message"
2) "news"
3) "weizhenping" #此內容爲頻道發送過來的消息
基於模式的頻道訂閱示例
1、基於模式訂閱頻道
[root@Centos7 ~]# redis-cli -h 172.16.36.70
172.16.36.70:6379> PSUBSCRIBE news.i[to] #訂閱了news.io,news,io兩個頻道
Reading messages... (press Ctrl-C to quit)
1) "psubscribe"
2) "news.i[to]"
3) (integer) 1
2、向頻道發送消息
172.16.36.70:6379> PUBLISH news.io hello
(integer) 1
3、頻道會接收下來消息
[root@Centos7 ~]# redis-cli -h 172.16.36.70
172.16.36.70:6379> PSUBSCRIBE news.i[to]
Reading messages... (press Ctrl-C to quit)
1) "psubscribe"
2) "news.i[to]"
3) (integer) 1
1) "pmessage"
2) "news.i[to]"
3) "news.io"
4) "hello"
redis的持久化功能
-
1、RDB(redisDB)
-
工作原理
RDB爲snapshot(快照)存儲機制,其也是redis默認的存儲機制,按照事先定製的策略,週期性地將數據從內存中讀取出來保存至磁盤,當到達save
指令指定的時間,redis主進程將fork一個子進程,負責內存中的內容快照並保存到磁盤中。 Linux系統有寫時複製機制,父進程與子進程會共享相同的物理頁面,當父進程處理寫請求時,操作系統爲寫的數據創建一個副本,因此子進程保存的數據一定是與時間點一致的數據。當子進程將快照寫入臨時文件後,會使用臨時文件替換舊的文件,然後子進程完成退出 。保存的數據文件默認爲dump.rdb
. 如果在SAVE週期之前停電了,會造成部分數據丟失。 -
數據保存機制
-
save
: 在主線程中保存快照,保存時會阻塞所有客戶端請求,每次將完整數據寫至dump.rdb文件中,會帶來大量的IO壓力 -
bgsave
: 異步保存機制,在後端自動保存,其不會阻塞窩客戶端請求
-
-
RDB相關的配置參數(/etc/redis/redis.conf)
-
stop-writes-on-bgsave-error yes
: 在基於快照備份時,一旦發生錯誤,是否停止寫操作 -
rdbcompression yes
: rdb文件是否壓縮來節約空間 -
rdbchecksum yes
: 是否對rdb的鏡像文件做校驗碼檢測,當redis啓動時會根據事先保存好的校驗碼進行對比,保證數據的完整性 -
dbfilename dump.rdb
: 保存的文件名 -
dir /var/lib/redis/
: 文件保存目錄 -
save ""
: 關閉rdb功能
-
-
-
2、AOF(append only file)
-
工作原理
redis以順序IO的方式附加在文件的尾部,將每一次的寫命令操作都通過write函數追加到文件後面,其是比RDB更好的持久化方案,但文件會變得越來越大。當redis重啓時,可通過執行文件中的命令在內存中重建數據庫
-
數據保存機制
-
bgrewriteaof
:AOF文件重寫
,它不會讀取正在使用的AOF文件,而是通過將內存中的數據以命令的方式保存至臨時文件中,完成之後替換原來的AOF文件,這樣可以減少AOF的大小
-
-
AOF重寫過程
- 1、redis主進程通過fork機制創建子線程
- 2、子進程根據redis內存中現有的數據通過重建命令創建數據庫於臨時文件中
- 3、父進程繼續接收客戶請求,並會把這些請求中的寫操作繼續追加到原來的AOF文件中,額外地,也將新的寫請求放置於一個緩衝隊列中
- 4、子進程重寫完成,會通知父進程,父進程把緩衝中的隊列命令寫到臨時文件中
- 5、父進程用臨時文件替換老的AOF文件
-
AOF相關的配置參數(/etc/redis/redis.conf)
-
appendonly no
: 是否啓用AOF功能,yes表示啓用 -
appendfilename "appendonly.aof"
: aof存儲文件 -
appendfsync always
: 每次收到寫命令,立即寫入磁盤 -
appendfsync everysec
: 每秒鐘寫一次,推薦操作 -
appendfsync no
: append功能自己觸發寫操作,將所有操作都提交給OS,由操作系統決定什麼時候寫 -
no-appendfsync-no-rewrite no
: 在重寫的過程中是否調用fsync -
auto-aof-rewrite-percentage 100
: 在aof文件已經是上次重寫時的2倍大小,將自動啓動重寫操作 -
auto-aof-rewrite-min-size 64mb
: 當文件達到64MB才執行重寫操作RDB與AOF同時啓用時: 1、bgsave和bgrewriteaof不會同時執行 2、在redis服務器啓動用於恢復數據時,會優先使用AOF
-
-
redis的主從複製
-
1、redis的主從複製特點
- 一個master可以有多個slave
- 支持鏈式複製
- master以非阻塞方式同步數據至slave,意味着可同時與多個slave同步
-
2、複製的工作原理
- 1、主庫會自己基於ping check機制來檢查從庫是否在線
- 2、如果從庫在線就同步數據文件至從服務器端
- 3、從服務器也可以發送請求同步的請求,主庫將啓動一個線程,把內存中的數據同步給從庫,從庫將數據保存至文件中
- 4、從庫再把文件裝載到內存中,從而完成複製功能
-
3、主從相關配置(/etc/redis.conf)
-
slave-serve-stale-data yes
: 當主服務器連接不上了,從服務器是否可以使用過期數據響應 -
repl-diskless-sync no
: 是否基於diskless機制同步 -
slave-priority 100
: 指定從服務器優先級 -
min-slave-to-write 3
: 如果從節點小於三個,主服務器將拒絕寫操作 -
min-slave-max-lag 10
: 從服務器不能晚於主服務器10秒鐘,是否將停止複製如果master使用了requirepass開啓了認證功能,從服務器要使用masterauth <password>來連接,使用指定的密碼進行認證
主從設置示例: 172.16.36.70 : 主redis服務 172.16.36.71 : 從redis服務 172.16.36.70配置 vim /etc/redis.conf bind 172.16.36.70 172.16.36.71配置: vim /etc/redis.conf bind 172.16.36.71 [root@Centos7 ~]# redis-cli -h 172.16.36.71 172.16.36.71:6379> SLAVEOF 172.16.36.70 6379 OK 172.16.36.71:6379> get ip #查看是否能獲取到主庫數據 "172.16.36.70" 172.16.36.71:6379> dbsize (integer) 3
-
redis高可用的實現
-
sentinel機制
-
工作原理
找一臺專用的監控主機,即能提供監控又可以提供配置功能,如果發現master離線了,監控主機會從從節點選擇新的主節點。爲了不誤判,setinel至少奇數個節點,同時監控。如果主節點不在線,多個setinel會協調一個新的主節點,以免發生誤判,所有setinel每秒一次向所有服務器發送ping請求,判斷節點是否在線。setinel是一個分佈式系統,使用流言協議和投票協議來決定故障遷移。可以監控多組redis實例。
-
sentinel的功用
- 用於管理多個redis服務,實現HA
- 監控
- 通知
- 自動故障轉移
-
工作過程
- 啓用sentinel時, 首先服務器做自身初始化,運行redis-server中專用於sentinel功能中的代碼
- 初始化sentinel狀態,根據給定的配置文件,初始化監控的master服務列表(可以根據master的配置,獲取從服務器節點)
- 創建連向Master的連接
-
sentinel下線機制
-
主觀下線
: 一個sentinel實例判斷出某節點下線 -
客觀下線
: 多個sentinel節點協商後判斷出某節點下線
-
-
-
setinel程序
-
redis-sentinel /path/to/sentinel.conf
-
redis-server /path/to/sentinel --sentinel
-
-
setinel的工作端口
-
26379/TCP
-
-
專用配置文件
-
/etc/redis-sentinel.conf
-
-
redis-sentinel.conf配置參數
-
prot 26379
-
dir /tmp
-
sentinel monitor mymaster 127.0.0.1 6379 2
mymaster: sentinel要監控的實例名稱,此名稱可以隨意取 127.0.0.1 : 主節點的IP地址 6379 : 主節點的端口 2 : sentinel節點的票數,此值要大於sentinel節點數量的半數
-
sentinel down-after-milliseconds mymaster 30000
: 判斷主節點不在線的默認超時時長,默認30秒 -
sentinel parallel-syncs mymaster 1
: 故障轉移時最多能有多少個從服務器向主服務器發起同步請求 -
sentinel failover-timeout mymaster 180000
: 提升主節點的超時時長,表示提升新的主節點在3分鐘內未完成,操作將失敗
-
-
sentinel專用命令
-
sentinel masters
: 列出所有主服務器 -
sentinel slaves <master name>
: 獲取所有當前redis實例中的從節點信息 -
sentinel get-master-addr-by name <master name>
:直接獲取當前redis實例主節點的IP地址及端口172.16.36.74:26379> sentinel get-master-addr-by-name mymaster 1) "172.16.36.72" 2) "6379"
-
sentinel reset
: 重置服務器所有狀態 -
sentinel failover <master name>
: 手動實現故障轉移
-
實驗環境說明:
172.16.36.70 : redis主節點
172.16.36.71 : redis從節點
172.16.36.72 : redis從節點
172.16.36.74 : sentinel節點1
172.16.36.75 : sentinel節點2
172.16.36.76 : sentinel節點3
####配置redis主節點
操作主機: 172.16.36.70
#vim /etc/redis.conf
bind 172.16.36.70
daemonize yes
啓動服務
#redis-server /etc/redis.conf
[root@Centos7 ~]# ss -tnl
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 172.16.36.70:6379 *:*
####配置redis從節點
操作主機: 172.16.36.71
#vim /etc/redis.conf
bind 172.16.36.71
daemonize yes
啓動服務
#redis-server /etc/redis.conf
[root@Centos7 ~]# ss -tnl
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 172.16.36.70:6379 *:*
配置主節點信息
[root@Centos7 ~]# redis-cli -h 172.16.36.71 -p 6379
172.16.36.71:6379> SLAVEOF 172.16.36.70 6379
OK
操作主機: 172.16.36.72
#vim /etc/redis.conf
bind 172.16.36.72
daemonize yes
啓動服務
#redis-server /etc/redis.conf
[root@Centos7 ~]# ss -tnl
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 172.16.36.70:6379 *:*
配置主節點信息
[root@Centos7 ~]# redis-cli -h 172.16.36.71 -p 6379
172.16.36.71:6379> SLAVEOF 172.16.36.70 6379
OK
####配置sentinel節點
操作主機: 172.16.36.74
# vim /etc/redis-sentinel.conf
port 26379
dir "/tmp"
daemonize yes
sentinel monitor mymaster 172.16.36.70 6379 2
sentinel parallel-syncs mymaster 3
sentinel down-after-milliseconds mymaster 30000
sentinel failover-timeout mymaster 180000
啓動服務
redis-sentinel /etc/redis-sentinel.conf
查看服務啓動狀態
users:(("master",2112,14))
[root@Centos7 ~]# ss -tln
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 *:26379 *:*
操作主機: 172.16.36.75
# vim /etc/redis-sentinel.conf
port 26379
dir "/tmp"
daemonize yes
sentinel monitor mymaster 172.16.36.70 6379 2
sentinel parallel-syncs mymaster 3
sentinel down-after-milliseconds mymaster 30000
sentinel failover-timeout mymaster 180000
啓動服務
redis-sentinel /etc/redis-sentinel.conf
查看服務啓動狀態
users:(("master",2112,14))
[root@Centos7 ~]# ss -tln
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 *:26379 *:*
操作主機: 172.16.36.76
# vim /etc/redis-sentinel.conf
port 26379
dir "/tmp"
daemonize yes
sentinel monitor mymaster 172.16.36.70 6379 2
sentinel parallel-syncs mymaster 3
sentinel down-after-milliseconds mymaster 30000
sentinel failover-timeout mymaster 180000
啓動服務
redis-sentinel /etc/redis-sentinel.conf
查看服務啓動狀態
users:(("master",2112,14))
[root@Centos7 ~]# ss -tln
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 *:26379 *:*
查看sentinel相關的日誌信息
tailf /var/log/redis/redis-sentinel.log
[32524] 25 Mar 10:05:02.290 # Sentinel runid is a44025e518b65c512340c48535df119496f7a0d8
[32524] 25 Mar 10:05:02.291 # +monitor master mymaster 172.16.36.70 6379 quorum 2
[32524] 25 Mar 10:05:32.322 # +sdown slave 172.16.36.71:6379 172.16.36.71 6379 @ mymaster 172.16.36.70 6379
[32524] 25 Mar 10:05:46.311 * +sentinel sentinel 172.16.36.76:26379 172.16.36.76 26379 @ mymaster 172.16.36.70 6379
[32524] 25 Mar 10:05:57.071 * +sentinel sentinel 172.16.36.75:26379 172.16.36.75 26379 @ mymaster 172.16.36.70 6379
[32524] 25 Mar 10:09:03.727 # +sdown master mymaster 172.16.36.70 6379
將當前的Master節點shudown,查看sentinel的相關日誌信息
[32524] 25 Mar 10:09:03.747 # +new-epoch 4
[32524] 25 Mar 10:09:03.749 # +vote-for-leader 90c011868befc3047a8527886efce8f8c6f9ea34 4
[32524] 25 Mar 10:09:03.836 # +odown master mymaster 172.16.36.70 6379 #quorum 3/2
[32524] 25 Mar 10:09:03.836 # Next failover delay: I will not start a failover before Fri Mar 25 10:15:04 2016
[32524] 25 Mar 10:09:04.854 # +config-update-from sentinel 172.16.36.75:26379 172.16.36.75 26379 @ mymaster 172.16.36.70 6379
[32524] 25 Mar 10:09:04.854 # +switch-master mymaster 172.16.36.70 6379 172.16.36.72 6379
[32524] 25 Mar 10:09:04.855 * +slave slave 172.16.36.71:6379 172.16.36.71 6379 @ mymaster 172.16.36.72 6379
[32524] 25 Mar 10:09:04.856 * +slave slave 172.16.36.70:6379 172.16.36.70 6379 @ mymaster 172.16.36.72 6379
對當前主節點監控sentinel的活躍探測信息
root@Centos7 ~]# redis-cli -h 172.16.36.72
172.16.36.72:6379> monitor
OK
1458878723.052705 [0 172.16.36.76:53255] "PING"
1458878723.402835 [0 172.16.36.75:38413] "PING"
1458878723.586806 [0 172.16.36.74:32824] "PING"
1458878723.859748 [0 172.16.36.75:38413] "PUBLISH" "__sentinel__:hello" "172.16.36.75,26379,90c011868befc3047a8527886efce8f8c6f9ea34,4,mymaster,172.16.36.72,6379,4"
1458878724.099837 [0 172.16.36.76:53255] "PING"
1458878724.152776 [0 172.16.36.76:53255] "PUBLISH" "__sentinel__:hello" "172.16.36.76,26379,21a0a795010287138b6efc636d03edcce66bcd56,4,mymaster,172.16.36.72,6379,4"
1458878724.454214 [0 172.16.36.75:38413] "PING"
1458878724.617819 [0 172.16.36.74:32824] "PING"
1458878724.693888 [0 172.16.36.74:32824] "PUBLISH" "__sentinel__:hello" "172.16.36.74,26379,a44025e518b65c512340c48535df119496f7a0d8,4,mymaster,172.16.36.72,6379,4"
使用info sentinel命令查看主從信息
172.16.36.74:26379> info sentinel
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
master0:name=mymaster,status=ok,address=172.16.36.72:6379,slaves=2,sentinels=3
Redis Clustering
在redis3.0版本中引入clustering功能, 是去中心化的分佈式數據庫,通過分片機制進行數據分佈,clustering內的每個節點僅有數據庫一部分數據,每個節點都有全局元數據,通過查找元數據,即可查詢到數據存放在哪臺服務器
分佈式解決方案
-
Twemproxy(Twitter)
- 代理分片機制
-
優點
- 非常穩定,企業方案
-
缺點
- 單點故障
- 需要依賴第三方軟件,如Keeplived
- 無法平滑地橫向擴展
- 沒有後臺界面
- 代理分片機制引入更多的來回次數並提高延遲
- 單核模式,無法充分利用多核,除非多實例
- Twitter官方肉串不再繼續使用
-
Codis(豌豆莢)
- 代理分片機制
- 2014年11月開源
- 基於GO以及C語言開發
-
優點
- 非常穩定,企業級方案
- 數據自動平衡
- 高性能
- 簡單的測試顯示較Twemproxy快一倍
- 善用多核CPU
-
簡單
- 沒有paxos類的協調機制
- 沒有主從複製
- 有後臺界面
-
缺點
- 代理分片機制引入更多的來回次數並提高延遲
-
需要第三方軟件支持協調機制
- 目前支持zookeeper及Etcd
- 不支持主從複製 ,需要另外實現
-
Codis採用proxy方案,所有必然會帶來單機性能的損失
- 經測試,在不開Pipeline的情況下,大概會損失40%左右的性能
-
Redis Cluster(官方)
- 官方實現
- 需要3.0或更高版本
-
優點
- 無中心的P2P Gossip分散式模式
- 更少的來回次數並降低延遲
- 自動於多個redis節點進行分片
- 不需要第三方軟件支持協調機制
-
缺點
- 依賴於redis 3.0或更高版本
- 需要時間驗證其穩定性
- 沒有後臺界面
- 需要智能客戶端
- redis客戶端必須支持redis cluster架構
- 較Codis有更多的維護升級版本