NoSQL 開發中或多或少都會用到,也是面試必問知識點。最近這幾天的面試每一場都問到了。但是感覺回答的並不好,還有很多需要梳理的知識點。這裡通過幾篇 Redis 筆記整個梳理一遍,後面再加上面試題。 Redis 系列: 1. Redis系列(一)Redis入門 2. Redis系列(二)Redi... ...
NoSQL 開發中或多或少都會用到,也是面試必問知識點。最近這幾天的面試每一場都問到了。但是感覺回答的並不好,還有很多需要梳理的知識點。這裡通過幾篇 Redis 筆記整個梳理一遍,後面再加上面試題。
Redis 系列:
- Redis系列(一)Redis入門
- Redis系列(二)Redis的8種數據類型
- Redis系列(三)Redis的事務和Spring Boot整合
- Redis系列(四)Redis配置文件和持久化
- Redis系列(五)發佈訂閱模式、主從複製和哨兵模式
- Redis系列(六)Redis 的緩存穿透、緩存擊穿和緩存雪崩
- Redis命令參考
1、Redis.conf 詳解
找到啟動時指定的配置文件:
[root@itzhouc ~]# cd /usr/local/bin
[root@itzhouc bin]# ls
dump.rdb jemalloc.sh kconfig luajit mcrypt redis-benchmark redis-check-rdb redis-sentinel
jemalloc-config jeprof libmcrypt-config luajit-2.0.4 mdecrypt redis-check-aof redis-cli redis-server
[root@itzhouc bin]# cd kconfig/
[root@itzhouc kconfig]# vim redis.conf
1、單位
# Redis configuration file example.
#
# Note that in order to read the configuration file, Redis must be
# started with the file path as first argument:
#
# ./redis-server /path/to/redis.conf
# Note on units: when memory size is needed, it is possible to specify
# it in the usual form of 1k 5GB 4M and so forth:
#
# 1k => 1000 bytes
# 1kb => 1024 bytes
# 1m => 1000000 bytes
# 1mb => 1024*1024 bytes
# 1g => 1000000000 bytes
# 1gb => 1024*1024*1024 bytes
#
# units are case insensitive so 1GB 1Gb 1gB are all the same.
配置文件中 unit 單位對大小寫不敏感。
2、包含
################################## INCLUDES ###################################
# Include one or more other config files here. This is useful if you
# have a standard template that goes to all Redis servers but also need
# to customize a few per-server settings. Include files can include
# other files, so use this wisely.
#
# Notice option "include" won't be rewritten by command "CONFIG REWRITE"
# from admin or Redis Sentinel. Since Redis always uses the last processed
# line as value of a configuration directive, you'd better put includes
# at the beginning of this file to avoid overwriting config change at runtime.
#
# If instead you are interested in using includes to override configuration
# options, it is better to use include as the last line.
#
# include /path/to/local.conf
# include /path/to/other.conf
配置文件可以將多個配置文件合起來使用。
3、NETWORK 網路
bind 127.0.0.1 # 綁定的 IP
protected-mode no # 保護模式
port 6379 # 埠設置
4、GENERAL 通用
daemonize yes # 以守護進程的方式運行,預設是 no ,我們需要自己開啟為 yes
pidfile /var/run/redis_6379.pid # 如果是後臺啟動,我們需要指定一個pid 文件
# 日誌級別
# Specify the server verbosity level.
# This can be one of:
# debug (a lot of information, useful for development/testing)
# verbose (many rarely useful info, but not a mess like the debug level)
# notice (moderately verbose, what you want in production probably)
# warning (only very important / critical messages are logged)
loglevel notice
logfile "" # 日誌文件的位置
databases 16 # 資料庫的數量,預設是 16
always-show-logo yes # 是否總是顯示 LOGO
5、快照 SNAPSHOTTING
持久化,在規定的時間內,執行了多少次操作則會持久化到文件
Redis 是記憶體資料庫,如果沒有持久化,那麼數據斷電即失。
################################ SNAPSHOTTING ################################
#
# Save the DB on disk:
#
# save <seconds> <changes>
#
# Will save the DB if both the given number of seconds and the given
# number of write operations against the DB occurred.
#
# In the example below the behaviour will be to save:
# after 900 sec (15 min) if at least 1 key changed
# after 300 sec (5 min) if at least 10 keys changed
# after 60 sec if at least 10000 keys changed
#
# Note: you can disable saving completely by commenting out all "save" lines.
#
# It is also possible to remove all the previously configured save
# points by adding a save directive with a single empty string argument
# like in the following example:
#
# save ""
# 如果 900s 內,至少有 1 個 key 進行了修改,進行持久化操作
save 900 1
# 如果 300s 內,至少有 10 個 key 進行了修改,進行持久化操作
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes # 如果持久化出錯,是否還要繼續工作
rdbcompression yes # 是否壓縮 rdb 文件,需要消耗一些 cpu 資源
rdbchecksum yes # 保存 rdb 文件的時候,進行錯誤的檢查校驗
dir ./ # rdb 文件保存的目錄
6、SECURITY 安全
可以設置 Redis 的密碼,預設是沒有密碼的。
[root@itzhouc bin]# redis-cli -p 6379
127.0.0.1:6379> ping
PONG
127.0.0.1:6379> config get requirepass # 獲取 redis 密碼
1) "requirepass"
2) ""
127.0.0.1:6379> config set requirepass "123456" # 設置 redis 密碼
OK
127.0.0.1:6379> ping
(error) NOAUTH Authentication required. # 發現所有的命令都沒有許可權了
127.0.0.1:6379> auth 123456 # 使用密碼登錄
OK
127.0.0.1:6379> config get requirepass
1) "requirepass"
2) "123456"
127.0.0.1:6379>
7、CLIENTS 限制
################################### CLIENTS ####################################
# Set the max number of connected clients at the same time. By default
# this limit is set to 10000 clients, however if the Redis server is not
# able to configure the process file limit to allow for the specified limit
# the max number of allowed clients is set to the current file limit
# minus 32 (as Redis reserves a few file descriptors for internal uses).
#
# Once the limit is reached Redis will close all the new connections sending
# an error 'max number of clients reached'.
#
# maxclients 10000 # 設置能鏈接上 redis 的最大客戶端數量
# maxmemory <bytes> # redis 設置最大的記憶體容量
maxmemory-policy noeviction # 記憶體達到上限之後的處理策略
- noeviction:當記憶體使用達到閾值的時候,所有引起申請記憶體的命令會報錯。
- allkeys-lru:在所有鍵中採用lru演算法刪除鍵,直到騰出足夠記憶體為止。
- volatile-lru:在設置了過期時間的鍵中採用lru演算法刪除鍵,直到騰出足夠記憶體為止。
- allkeys-random:在所有鍵中採用隨機刪除鍵,直到騰出足夠記憶體為止。
- volatile-random:在設置了過期時間的鍵中隨機刪除鍵,直到騰出足夠記憶體為止。
- volatile-ttl:在設置了過期時間的鍵空間中,具有更早過期時間的key優先移除。
8、APPEND ONLY 模式 AOF 配置
appendonly no # 預設是不開啟 AOF 模式的,預設使用 rdb 方式持久化,大部分情況下,rdb 完全夠用
appendfilename "appendonly.aof" # 持久化的文件的名字
# appendfsync always # 每次修改都會 sync 消耗性能
appendfsync everysec # 每秒執行一次 sync 可能會丟失這 1s 的數據。
# appendfsync no # 不執行 sync 這個時候操作系統自己同步數據,速度最快。
2、持久化(面試和工作重點)
面試和工作,持久化都是重點。
Redis 是記憶體資料庫,如果不將記憶體中的資料庫狀態保存到磁碟,那麼一旦伺服器進程退出,伺服器中的資料庫狀態就會消失,所以 Redis 提供了持久化功能。
1、RDB (Redis DataBase)
什麼是 RDB
在指定的時間間隔內,將記憶體中的數據集快照寫入磁碟,也就是 Snapshot 快照,它恢復時是將快照文件直接讀取到記憶體里的。
Redis 會單獨創建(fork)一個子進程進行持久化,會先將數據寫入一個臨時文件中,待持久化過程結束了,再用這個臨時文件替換上次持久化好的文件。整個過程中,主進程不進行任何 IO 操作,這就確保的極高的性能。如果需要大規模的數據的恢復,且對數據恢復的完整性不是非常敏感,那 RDB 方式要比 AOF 方式更加高效。RDB 唯一的缺點是最後一次持久化的數據可能會丟失。
生產環境下,需要對這個文件記性
預設持久化方式是 RDB,一般不需要修改。
rdb 保存的文件是 dump.rdb :
# The filename where to dump the DB
dbfilename dump.rdb
測試1:
首先修改配置文件保存快照的策略
################################ SNAPSHOTTING ################################
#
# Save the DB on disk:
#
# save <seconds> <changes>
#
# save ""
# save 900 1
# save 300 10
# save 60 10000
save 60 5 # 只要 60s 內修改了 5 次 key 就會觸發 rdb 操作。
保存配置文件:
127.0.0.1:6379> save
OK
127.0.0.1:6379>
刪除原始的 dump.rdb 文件:
[root@itzhouc bin]# ls
dump.rdb jemalloc.sh kconfig luajit mcrypt redis-benchmark redis-check-rdb redis-sentinel
jemalloc-config jeprof libmcrypt-config luajit-2.0.4 mdecrypt redis-check-aof redis-cli redis-server
[root@itzhouc bin]# rm -rf dump.rdb
[root@itzhouc bin]# ls
jemalloc-config jeprof libmcrypt-config luajit-2.0.4 mdecrypt redis-check-aof redis-cli redis-server
jemalloc.sh kconfig luajit mcrypt redis-benchmark redis-check-rdb redis-sentinel
[root@itzhouc bin]#
60s 內修改 5 次 key :
127.0.0.1:6379> set k1 v1
OK
127.0.0.1:6379> set k2 v2
OK
127.0.0.1:6379> set k3 v3
OK
127.0.0.1:6379> set k4 v4
OK
127.0.0.1:6379> set k5 v5
OK
dump.rdb 文件再次出現。
[root@itzhouc bin]# ls
dump.rdb jemalloc.sh kconfig luajit mcrypt redis-benchmark redis-check-rdb redis-sentinel
jemalloc-config jeprof libmcrypt-config luajit-2.0.4 mdecrypt redis-check-aof redis-cli redis-server
[root@itzhouc bin]#
恢複數據:
關閉 Redis 服務和客戶端,再次進入時數據被自動恢復:
127.0.0.1:6379> shutdown # 關閉 Redis 服務
not connected> exit
[root@itzhouc bin]# ps -ef|grep redis # redis 已經關閉了
root 25989 23576 0 14:27 pts/1 00:00:00 grep --color=auto redis
[root@itzhouc bin]# redis-server kconfig/redis.conf # 再次開啟服務
25994:C 02 May 2020 14:28:01.003 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
25994:C 02 May 2020 14:28:01.003 # Redis version=5.0.8, bits=64, commit=00000000, modified=0, pid=25994, just started
25994:C 02 May 2020 14:28:01.003 # Configuration loaded
[root@itzhouc bin]# redis-cli -p 6379 # 客戶端連接
127.0.0.1:6379> get k2 # 可以直接獲取數據,說明k2 被持久化了。
"v2"
127.0.0.1:6379>
測試2:
刪除 dump.rdb 文件
root@itzhouc bin]# rm -rf dump.rdb
[root@itzhouc bin]# ls
jemalloc-config jeprof libmcrypt-config luajit-2.0.4 mdecrypt redis-check-aof redis-cli redis-server
jemalloc.sh kconfig luajit
在客戶端清除所有數據:
127.0.0.1:6379> flushall
OK
再次檢驗 dump.rdb 文件:
[root@itzhouc bin]# ls
dump.rdb jemalloc.sh kconfig luajit mcrypt redis-benchmark redis-check-rdb redis-sentinel
jemalloc-config jeprof libmcrypt-config luajit-2.0.4 mdecrypt redis-check-aof redis-cli redis-server
[root@itzhouc bin]#
dump.rdb 文件再次出現。
觸發機制
1、save 的規則滿足的情況下,會自動觸發 rdb 規則
2、執行 flushall 命令,也會觸發 rdb 規則
3、退出 redis 也會產生 rdb 文件
備份就自動生成一個 dump.rdb 文件。
如何恢復 rdb 文件
1、只需要將 rdb 文件放在 Redis 啟動目錄就可以,Redis 啟動的時候會自動檢查 dump.rdb ,恢復其中的數據;
2、查看存放 rdb 文件的位置,在客戶端中使用如下命令。
127.0.0.1:6379> config get dir
1) "dir"
2) "/usr/local/bin" # 如果在這個目錄下存在 dump.rdb 文件,啟動就會自動恢復其中的數據
127.0.0.1:6379>
RDB 的優缺點
優點:
1、適合大規模的數據恢復
2、對數據的完整性要求不高
缺點:
1、需要一定的時間間隔進行操作,如果 Redis 意外宕機,最後一次修改的數據就沒有了
2、fork 進程的時候,會占用一定的空間。
2、AOF (Append Only File)
AOF( append only file )持久化以獨立日誌的方式記錄每次寫命令,併在 Redis 重啟時在重新執行 AOF 文件中的命令以達到恢複數據的目的。AOF 的主要作用是解決數據持久化的實時性。
以日誌形式來記錄每個操作,將 Redis 執行的過程的所有指令記錄下來(讀操作不記錄),只追加文件但不可以改寫文件,redis 啟動之初會讀取該文件重新構建數據,換言之,redis 重啟的話就根據日誌文件的內容將寫指令從前到後執行一遍以完成數據的恢復工作。
AOF 保存的是 appendonly.aof 文件。
開啟 AOF 模式
將配置文件中預設為 no 的 appendonly 修改為 yes ,重啟服務。
appendonly yes
# The name of the append only file (default: "appendonly.aof")
appendfilename "appendonly.aof"
重啟後可以看到 AOF 文件:
[root@itzhouc bin]# ls
appendonly.aof ipsort jeprof logs mcrypt redis-benchmark redis-cli tntrecht
backup.db jemalloc-config kconfig luajit mdecrypt redis-check-aof redis-sentinel
dump.rdb jemalloc.sh libmcrypt-config luajit-2.0.4 pnscan redis-check-rdb redis-server
但是文件是空的。使用客戶端添加一些數據再次查看:
[root@itzhouc bin]# redis-cli -p 6379
127.0.0.1:6379> set k1 v1
OK
127.0.0.1:6379> set k2 v2
OK
127.0.0.1:6379> set k3 v3
OK
127.0.0.1:6379>
[root@itzhouc bin]# cat appendonly.aof
*2
$6
SELECT
$1
0
*3
$3
set
$2
k1
$2
v1
*3
$3
set
$2
k2
$2
v2
*3
$3
set
$2
k3
$2
v3
自動修複 AOF文件
如果手動修改AOF 文件,可能導致 Redis 服務不能啟動。比如這裡我手動在 AOF 文件的最後一行隨便添加一些命令:
set
$2
k3
$2
v3
gjjjjjjjjj
刪除 dump.rdb 文件,重啟服務:
[root@itzhouc bin]# rm -rf dump.rdb
[root@itzhouc bin]# ls
appendonly.aof jemalloc.sh libmcrypt-config luajit-2.0.4 pnscan redis-check-rdb redis-server
ipsort jeprof logs mcrypt redis-benchmark redis-cli tntrecht
jemalloc-config kconfig luajit mdecrypt redis-check-aof redis-sentinel
[root@itzhouc bin]# redis-server kconfig/redis.conf
13746:C 02 May 2020 16:22:43.345 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
13746:C 02 May 2020 16:22:43.346 # Redis version=5.0.8, bits=64, commit=00000000, modified=0, pid=13746, just started
13746:C 02 May 2020 16:22:43.346 # Configuration loaded
[root@itzhouc bin]# redis-cli -p 6379
Could not connect to Redis at 127.0.0.1:6379: Connection refused # 連接失敗
not connected>
如果這個 AOF 文件有錯位,客戶端就不能鏈接了,需要修複 AOF 文件。Redis 提供了工具 redis-check-aof --fix
[root@itzhouc bin]# redis-check-aof --fix appendonly.aof
0x 6e: Expected prefix '*', got: 'g'
AOF analyzed: size=122, ok_up_to=110, diff=12
This will shrink the AOF from 122 bytes, with 12 bytes, to 110 bytes
Continue? [y/N]: y
Successfully truncated AOF
[root@itzhouc bin]#
重啟服務,再次嘗試鏈接成功。
AOF 的優缺點
appendonly yes # 預設是 no
appendfilename "appendonly.aof" # 持久化的文件的名字
# appendfsync always # 每次修改都會 sync ,消耗性能
appendfsync everysec # 每秒執行一次 sync ,可能會丟失這 1s 的數據
# appendfsync no # 不執行 sync,這個時候操作系統自己同步數據,速度最快
優點:
1、每一次修改都同步,文件的完整性更加好
2、每秒同步一次,可能會丟失一秒的數據
3、從不同步,效率最高的
缺點:
1、相對於數據文件來說, AOF 遠遠大於 RDB ,修複的速度也比 RDB 慢
2、AOF 的運行效率也比 RDB 慢,所以 Redis 預設的配置就是 RDB 持久化。
3、擴展
1、RDB 持久化方式能夠在指定的時間間隔內對你的數據進行快照存儲
2、AOF 持久化方式記錄每次對伺服器寫的操作,當伺服器重啟的時候會重新執行這些命令來恢複原始的數據,AOF 命令以Redis 協議追加保存每次寫的操作到文件尾部,Redis 還能對 AOF 文件記性後臺重寫,使得AOF 文件的體積不至於過大
3、只做緩存,如果你只希望你的數據在伺服器運行的時候存在,你也可以不使用任何持久化
4、同時開啟兩種持久化方式
- 在這種情況下,當 Redis 重啟的時候會優先載入AOF 文件來恢複原始的數據,因為在通常情況下,AOF 文件保存的數據集要比 RDB 文件保存的數據集要完整。
- RDB 的數據不實時,同步使用兩者時伺服器重啟也只會找 AOF 文件。那要不要只使用 AOF 呢?作者建議不要,因為 RDB 更適合用於備份資料庫(AOF 在不斷變化不好備份),快速重啟,而且不會有 AOF 可能潛在的 BUG,留著作為一個萬一的手段。
5、性能建議
- 因為 RDB 文件只用作後備用途,建議只在 Slave 上持久化 RDB 文件,而且只要 15 分鐘備份一次就夠了,只保留save 900 1 這條規則。
- 如果 Enable AOF ,好處是在最惡劣情況下也只會丟失不超過兩秒的數據,啟動腳本較簡單隻 load 自己的 AOF 文件就可以了,代價是一是帶來了持續的IO,而是 AOF rewrite 的最後將rewrite 過程中產生的新數據寫到新文件造成的阻塞幾乎是不可避免的。只要硬碟許可,應該儘量減少 AOF rewrite 的頻率,AOF 重寫的基礎大小預設值是 64M 太小了,可以設置到 5G 以上,預設值超過原大小 100% 大小重寫可以改到適當的數值。
- 如果不 Enable AOF ,僅靠 Master-Slave Repllcation 實現高可用也可以,能省掉一大筆 IO ,也減少了 rewrite 時帶來的系統波動。代價是如果 Master/Slave 同時宕掉,會丟失十幾分鐘的數據,啟動腳本也要比較兩個 Master/Slave 中的 RDB 文件,載入較新的那個,微博就是這種架構。
下一篇筆記將介紹 Redis 的發佈訂閱模式、主從複製和哨兵模式。