Redis配置模板及持久化解決方案

前言

本文根據貴金屬使用Redis的經驗,整理了Redis服務端配置模板、哨兵配置模板、監控項部署、持久化解決方案、Jedis客戶端連接池配置說明,旨在減少大家在使用Redis過程中因爲配置不當引發的問題。

後續的文章鏈接中也給出了之前遇到的一些問題,以及對默認配置項進行選擇的原因,供大家參考。(Redis Server端版本2.8.19,客戶端使用Jedis2.6.0),截止到本文發表前Redis4.0已經release,但並不影響本文的配置選擇,4.0的新特性我們也會持續跟進,歡迎大家一起討論。

1. Redis哨兵模板

哨兵的部署至少3臺,物理機獨立部署,奇數個;

哨兵模板見附錄1

2. Redis Server模板

Server模板見附錄2

配置模板需要根據使用情況做調整:

1)根據Redis用途需要指定不同的key淘汰策略

Redis用作緩存(允許數據淘汰)

Redis作爲內存數據庫(不允許淘汰)

maxmemory-policy { allkeys-lruvolatile-lruallkeys-randomvolatile-randomvolatile-ttl }

maxmemory-policy noeviction

2)持久化方案選擇

cpu、磁盤性能是否支持持久化

支持

不支持

參考下面2種因素

Master關閉持久化Slave開啓rdb定時rdb同步

使用內存上限

超過10G

不超過10G

Master開啓aofslave開啓rdb定時腳本執行bgrewriteaof

Master開啓rdbSlave開啓rdb

能否容忍少量數據丟失

不能

Master開啓rdbslave開啓rdb

Master開啓aofSlave開啓rdb

需要根據使用場景綜合考慮三個因素的影響,評估可接受的方案。

備註:

1)Rdb定時同步主要防止主從切換失敗時手動啓動Master或誤重啓導致數據丟失(腳本見附錄3)。 2)不建議主備都開啓aof,slave開啓rdb可以防止aof文件損壞造成數據無法恢復。 3)選擇10G作爲rdb是否適用的閾值是因爲:

  • 新浪微博給的建議是不超過20G,而我們虛機上的測試,要想保證應用毛刺不明顯,內存建議在控制在10G以下。
  • 內存空間達到40G(考慮每個頁表條目消耗 8 個字節),那麼頁表大小就有80M,複製頁表有些虛擬機需要200ms以上,我們設置慢日誌的閾值是50ms,爲保證不被慢日誌捕獲內存也建議控制在10G以下。

3. Redis監控方案及閾值設置

1)連接數 監控項:check.redis.connected_clients.XXX 案例舉例:方法內部有耗時操作,導致連接數歸還緩慢,連接數上升;沒有正確歸還連接,導致連接數上升。

2)ops 監控項:check.redis.instantaneous_ops_per_sec.XXX 案例舉例:業務代碼有bug,導致頻繁的操作redis,導致ops上升。

3)內存使用 監控項:check.redis.used_memory.XXX 案例舉例:客戶端連續的hgetAll操作,請求數據過多,響應數據放入緩衝區,佔用了redis內存空間,導致內存使用突然飆升。

4)慢日誌開啓 在redis配置文件中配置慢日誌門限 slowlog-log-slower-than 50000 //表示redis操作超過50ms的操作記錄慢日誌 slowlog-max-len 1024 //慢日誌記錄最多保留1024個 通過在redis服務端使用slowlog get命令可以獲取最新的慢日誌記錄,通過慢日誌記錄排查操作耗時的命令並進行相應的調整。

5)cpu steal、cpu load 監控項:system.cpu.util.steal、system.cpu.load cpu steal或者cpu load過高,都有可能卡redis實例,導致業務超時等問題。 cpu steal過高如果是由於共享cpu導致的,可考慮調整爲獨享的方式;cpu load過高需要排查看是該機器上什麼操作影響的。

報警方案根據應用的具體情況來設置:

1)內存最大容量6G, 報警門限4G (75%左右) 2)連接數超過5000(最高10000)報警 (50%左右) 3)操作數每秒超過50000(最高100000)報警 (50%左右) 4)慢日誌50ms報警

4. 客戶端jedis連接池配置建議

JedisPoolConfig參考配置

<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxIdle" value="30" />       //JedisPool最大空閒連接數  
<property name="minIdle" value="10" />     //JedisPool最小空閒連接數,也即初始化連接數  
<property name="testOnBorrow" value="false" />   //從JedisPool獲取jedis實例時檢查連接的有效性,默認是false  
<property name="testWhileIdle" value="false" />     //表示有一個idle object evitor線程對idle object進行掃描,如果validate失敗,此object會被從pool中drop掉  
<property name="testOnReturn" value="true" />     //將jedis實例歸還連接池時檢查連接的有效性,默認是false ;test開啓太多會影響性能,都不開啓異常連接可能會被使用,建議至少開啓一個  
<property name="maxTotal" value="300"/>          //JedisPool最大連接數  
<property name="maxWaitMillis" value="4000"/>   //從JedisPool獲取連接等待毫秒數,超時則拋異常;若blockWhenExhausted爲false,該配置項無效  
<property name="blockWhenExhausted" value="false"/>   //blockWhenExhausted   表示連接耗盡時是否阻塞, false報異常,ture阻塞maxWaitMillis直到超時 ;不配默認是true;建議配置爲false  
</bean>

注:jedis的讀超時和連接超時都是timeout

配置模板參數設置原因可以參考 http://tech.lede.com/2017/07/03/rd/server/redisconfig/
附錄1

port {port} daemonize yes pidfile “/{HOME}/log/sentinel.pid” logfile “/{HOME}/log/sentinel.log” sentinel monitor master {ip address} {port} {quorum} /當哨兵數爲3的時候,quorum需配置爲2,哨兵數爲5的時候,quorum需配置爲3/ sentinel down-after-milliseconds master 60000 /哨兵與master失連1分鐘則主觀下線/ sentinel failover-timeout master 180000 sentinel config-epoch master 0

附錄2

1)Master配置: port {port} daemonize yes pidfile /{HOME}/log/redis.pid logfile /{HOME}/log/redis.log dir /{HOME}/data dbfilename dump.rdb requirepass {password} masterauth {password} timeout 0 loglevel notice databases 16 rdbcompression yes maxclients 10000 maxmemory {maxmemory} maxmemory-policy noeviction save 900 1 save 300 10 save 60 300 appendonly no appendfsync everysec no-appendfsync-on-rewrite yes auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb slowlog-log-slower-than 50000 slowlog-max-len 1024

client-output-buffer-limit normal 10mb 5mb 10 client-output-buffer-limit slave 1024mb 256mb 300 client-output-buffer-limit pubsub 32mb 8mb 60 lua-time-limit 1000

rename-command FLUSHALL SUPER_FLUSHALL rename-command FLUSHDB SUPER_FLUSHDB rename-command SHUTDOWN SUPER_SHUTDOWN rename-command KEYS SUPER_KEYS rename-command MONITOR SUPER_MONITOR

2)Slave配置: port {port} daemonize yes pidfile /{HOME}/log/redis.pid logfile /{HOME}/log/redis.log dir /{HOME}/data dbfilename dump.rdb requirepass {password} masterauth {password} timeout 0 loglevel notice databases 16 rdbcompression yes maxclients 10000 maxmemory {maxmemory} maxmemory-policy noeviction save 900 1 save 300 10 save 60 300

appendonly no appendfsync everysec no-appendfsync-on-rewrite yes auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb slowlog-log-slower-than 50000 slowlog-max-len 1024

client-output-buffer-limit normal 10mb 5mb 10 client-output-buffer-limit slave 1024mb 256mb 300 client-output-buffer-limit pubsub 32mb 8mb 60 lua-time-limit 1000

slaveof {ip address} {port}

rename-command FLUSHALL SUPER_FLUSHALL rename-command FLUSHDB SUPER_FLUSHDB rename-command SHUTDOWN SUPER_SHUTDOWN rename-command KEYS SUPER_KEYS rename-command MONITOR SUPER_MONITOR

附錄3
#!/bin/sh
project=$1
backup_dir="/home/redisInstance/$project/data/rdb_bak/"
if [ ! -d "$backup_dir" ]; then
   mkdir -p "$backup_dir"
fi
list=`ls /home/redisInstance/$project/data/rdb_bak/ | wc -l `
echo "[$(date +%Y%m%d-%H:%M:%S)]  the backup files number is $list"
result=$(find "$backup_dir" -amin +60 -name dump.rdb.* -print)
if [ $list -gt 13 ]
then
  if [ x"$result" = x ]
  then
     echo "[$(date +%Y%m%d-%H:%M:%S)]  no backup files found to delete!"
  else
     echo -e "[$(date +%Y%m%d-%H:%M:%S)]  backup files found to delete : \"$result\" !"
  fi
  find "$backup_dir" -amin +60 -name "dump.rdb.*"  -exec rm -rf {} \;
else
  echo "[$(date +%Y%m%d-%H:%M:%S)]  the backup files number is less than 13, no files allowed to delete"
fi
backuptime=$(date +%Y%m%d%H%M)
eval rsync -a /home/redisInstance/"$project"/data/dump.rdb "$backup_dir"dump.rdb."$backuptime"
cp "$backup_dir"dump.rdb."$backuptime" "$backup_dir"dump.rdb
if [ $? -eq 0 ]
then
   echo "[$(date +%Y%m%d-%H:%M:%S)]  the rdb file backup to local dir (rdb_bak) is OK"
else
   echo "[$(date +%Y%m%d-%H:%M:%S)]  the rdb file backup to local dir (rdb_bak) is error"
fi
rsynctime=$(date -d "-5 min" +%Y%m%d%H%M)
eval rsync -avzP /home/redisInstance/"$project"/data/rdb_bak/dump.rdb [email protected]::"$project" --password-file=/etc/rsyncd.secrets
if [ $? -eq 0 ]
then
   echo "[$(date +%Y%m%d-%H:%M:%S)]  the rdb file backup to remote host(10.120.117.165) dir (data) is OK"
else
   echo "[$(date +%Y%m%d-%H:%M:%S)]  the rdb file backup to remote host(10.120.117.165) dir (data) is error"
fi
rm -rf "$backup_dir"dump.rdb
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章