1、實驗環(huán)境
硬件:4C/1G/20G
軟件:Centos7/Docker19/Redis6
2入问、實驗步驟
2.1 初始準備
$ swapoff -a # 臨時關(guān)閉交換內(nèi)存
$ echo never > /sys/kernel/mm/transparent_hugepage/enabled # 臨時禁用 THP
$ echo never > /sys/kernel/mm/transparent_hugepage/defrag
$ mkdir -p /usr/local/redis && chmod 666 /usr/local/redis && cd /usr/local/redis
$ vi redis.conf # 添加如下內(nèi)容
appendonly no # 不開戶實例化匾灶,以提高性能
maxmemory 8M # 最大使用內(nèi)存
maxmemory-policy allkeys-lru # 當used_memory達到maxmemory時的數(shù)據(jù)驅(qū)逐策略颊糜,刪除最近最少用數(shù)據(jù)
protected-mode no # 開啟其他機器訪問
$ vi import.lua # 批量添加數(shù)據(jù)Lua腳本
local count = tonumber(ARGV[1])
local expire_time = tonumber(ARGV[2]) -- 過期時間(秒)
redis.call("SELECT", 0) -- 確保選擇數(shù)據(jù)庫 0
for i = 1, count do
local key = "key" .. i
local value = "value" .. i
redis.call("SET", key, value)
redis.call("EXPIRE", key, expire_time)
if i % 10000 == 0 then
redis.log(redis.LOG_NOTICE, "Inserted and set expiration for " .. i .. " keys")
end
end
2.2 運行docker
$ docker run --name redis --restart=always -d \
-p 6379:6379 \
-v /usr/local/redis/redis.conf:/usr/local/etc/redis/redis.conf \
-v /usr/local/redis/import.lua:/data/import.lua \
-v /usr/local/redis/data:/data redis:6.0.8 \
redis-server /usr/local/etc/redis/redis.conf
$ docker ps
\CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d007736e7bdd redis:6.0.8 "docker-entrypoint.s…" 16 seconds ago Up 15 seconds 0.0.0.0:6379->6379/tcp redis
2.3 實驗1:設(shè)置最大內(nèi)存與數(shù)據(jù)過期時間
使用top命令 憔杨,看一下當前內(nèi)存占用情況
再開一個SSH窗口,檢查一下配置參數(shù)是否生效
$ docker exec -it redis /bin/bash
root@d007736e7bdd:/data# redis-cli config get maxmemory
1) "maxmemory"
2) "8000000"
root@d007736e7bdd:/data# redis-cli config get maxmemory-policy
1) "maxmemory-policy"
2) "allkeys-lru"
檢查一下初始內(nèi)存分配情況
root@d007736e7bdd:/data# redis-cli info memory | grep used_memory|grep human
used_memory_human:844.73K
used_memory_rss_human:4.26M
used_memory_peak_human:844.73K
used_memory_lua_human:37.00K
used_memory_scripts_human:0B
參數(shù)說明:
used_memory:Redis 分配器分配的內(nèi)存總量
used_memory_rss:進程從操作系統(tǒng)分配的內(nèi)存總量
used_memory_peak:Redis 分配器分配的內(nèi)存峰值
寫20萬數(shù)據(jù),設(shè)置10分鐘過期
root@d007736e7bdd:/data# redis-cli info keyspace # 當前數(shù)據(jù)庫為空
# Keyspace
root@d007736e7bdd:/data# redis-cli --eval import.lua , 200000 600
(nil)
root@a3222c70b966:/data# redis-cli info memory | grep used_memory|grep human
used_memory_human:7.63M # 應該內(nèi)存已經(jīng)用盡了
used_memory_rss_human:30.89M # 實際占用內(nèi)存已經(jīng)遠超8M了
used_memory_peak_human:215.92M
used_memory_lua_human:74.00K
used_memory_scripts_human:552B
root@a3222c70b966:/data# redis-cli info keyspace
# Keyspace
db0:keys=30625,expires=30625,avg_ttl=538500 # 已經(jīng)觸發(fā)清除策略怀读,只剩下3萬條
過10分鐘后再檢查
root@a3222c70b966:/data# redis-cli info keyspace # 數(shù)據(jù)已完全過期
# Keyspace
root@a3222c70b966:/data# redis-cli info memory | grep used_memory|grep human
used_memory_human:846.61K
used_memory_rss_human:9.52M # 實際占用內(nèi)存已經(jīng)下降了
used_memory_peak_human:215.92M
used_memory_lua_human:74.00K
used_memory_scripts_human:552B
從下圖可以看到苍糠,雖然數(shù)據(jù)都被清理了拥娄,但實際占用內(nèi)存還是增長了
2.4 實驗2:設(shè)置最大內(nèi)存,不設(shè)置數(shù)據(jù)過期時間
$ docker stop redis && docker rm redis
redis
redis
$ rm -f import.lua
$ vi import.lua
for i = 1, count do
redis.call("SET", "key" .. i, "value" .. i)
end
$ docker run --name redis ........ (參考前面)
回到第2個窗口
$ docker exec -it redis /bin/bash
root@0fce85341f7e:/data# redis-cli --eval import.lua , 200000
(nil)
root@0fce85341f7e:/data# redis-cli info memory | grep used_memory|grep human
used_memory_human:7.63M
used_memory_rss_human:20.59M # 實際占用內(nèi)存比有過期設(shè)置的要少
used_memory_peak_human:16.55M
used_memory_lua_human:60.00K
used_memory_scripts_human:216B
root@0fce85341f7e:/data# redis-cli info keyspace
# Keyspace
db0:keys=70001,expires=0,avg_ttl=0 # 剩下7萬條
因為沒有設(shè)置過期時間摊欠,這里將數(shù)據(jù)庫手動清空
root@0fce85341f7e:/data# redis-cli FLUSHALL
OK
root@0fce85341f7e:/data# redis-cli info keyspace
# Keyspace
root@0fce85341f7e:/data# redis-cli info memory | grep used_memory|grep human
used_memory_human:845.52K # used_memory 恢復了
used_memory_rss_human:7.55M # 系統(tǒng)分配內(nèi)存也降下來了
used_memory_peak_human:16.55M
used_memory_lua_human:60.00K
used_memory_scripts_human:216B
2.5 實驗3:不設(shè)置最大內(nèi)存與數(shù)據(jù)過期時間
$ docker stop redis && docker rm redis
redis
redis
$ sed -i "s/max/#max/" redis.conf
[root@localhost redis]# cat redis.conf
appendonly no
#maxmemory 8M
#maxmemory-policy allkeys-lru
protected-mode no
$ docker run --name redis ........ (參考前面)
再到第二個窗口
$ docker exec -it redis /bin/bash
root@8e6f924f76df:/data# redis-cli info memory | grep used_memory|grep human
used_memory_human:844.73K
used_memory_rss_human:4.25M
used_memory_peak_human:844.73K
used_memory_lua_human:37.00K
used_memory_scripts_human:0B
root@8e6f924f76df:/data# redis-cli --eval import.lua , 200000 # 寫20萬條
(nil)
root@8e6f924f76df:/data# redis-cli info memory | grep used_memory|grep human
used_memory_human:16.55M
used_memory_rss_human:21.59M
used_memory_peak_human:16.55M
used_memory_lua_human:60.00K
used_memory_scripts_human:216B
root@8e6f924f76df:/data# redis-cli info keyspace
# Keyspace
db0:keys=200000,expires=0,avg_ttl=0 # 全部定入
直接寫200萬條試下
root@8e6f924f76df:/data# redis-cli --eval import.lua , 2000000
(nil)
root@8e6f924f76df:/data# redis-cli info keyspace
# Keyspace
db0:keys=2000000,expires=0,avg_ttl=0
root@8e6f924f76df:/data# redis-cli info memory | grep used_memory|grep human
used_memory_human:154.15M
used_memory_rss_human:161.43M
used_memory_peak_human:154.15M
used_memory_lua_human:58.00K
used_memory_scripts_human:216B
寫2000萬條
[root@localhost ~]# docker ps # 可以看到docker已經(jīng)重啟了( Up 7 seconds )
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8e6f924f76df redis:6.0.8 "docker-entrypoint.s…" 8 minutes ago Up 7 seconds 0.0.0.0:6379->6379/tcp redis
3说墨、實驗結(jié)論
由上述實驗可以看出:
- 不設(shè)置maxmemory時可以最大保證數(shù)據(jù)的完整性,但有可能導致docker程序因內(nèi)存占用過大而被系統(tǒng)重置棺棵;
- 在已經(jīng)設(shè)置了maxmemory的情況下,不主動配置數(shù)據(jù)過期時間可以較完整地保存數(shù)據(jù)缚柏,若配置了配置數(shù)據(jù)過期時間則可以減少內(nèi)存開銷币喧;
- maxmemory并不等于redis占用系統(tǒng)實際內(nèi)存的值,當有大批量數(shù)據(jù)寫入時史翘,后者的值有可能比前者大得多,因此這個值要合理設(shè)置跨琳。