Redis內存優化

1、鍵值設計

一、key名設計

三大建議redis

  • 可讀性和可管理性

以業務名(或數據庫名)爲前綴(防止key衝突),用冒號分隔,好比業務名:表名:id數據庫

  • 簡潔性

保證語義的前提下,控制key的長度,當key較多時,內存佔用也不容忽視 (embstr 3-39)json

  • 不包含特殊字符

反例:包含換行 等緩存

二、value設計
  • 拒絕bigkey
  • 選擇合適的數據結構
  • 過時設計

string類型控制在10kb以內
hash、list、set、zset元素個數不超過5000
反例 一個包含幾百萬個元素的list、hash等,一個巨大的json字符串
bigkey的危害安全

  • 網絡阻塞
  • 慢查詢
  • 節點數據不均衡
  • 反序列消耗
Redis客戶端自己不負責序列化
應用頻繁序列化和反序列化bigkey:本地緩存或者Redis緩存

bigkey發現網絡

  • 應用異常
  • redis-cli --bigkeys
  • scan + debug object
  • 主動報警
  • 內核熱點key問題優化
三、bigkey問題

bigkey的刪除數據結構

  • 阻塞:注意隱性刪除(rename、過時等)
  • lazy delete(unlink命令)

bigkey的預防併發

  • 優化數據結構:例如二級拆分
  • 物理隔離或者萬兆網卡:不是治標方案
  • 命令優化:例如hgetall->hget、hscan
  • 報警和按期優化

鍵值生命週期app

  • 週期數據須要設置過時時間,object idle time能夠找垃圾key-value
  • 過時時間不宜集中:緩存穿透和雪崩問題

命令優化運維

  • O(N)以上的命令關注N的數量
  • 禁用命令 keys flush flushdb等
  • 合理使用select redis的多數據庫較弱,使用數字進行區分 不少客戶端支持較差
  • Redis事物功能較弱,不建議過多使用
  • Redis集羣版本在使用Lua上有特殊要求
  • 必要狀況下使用monitor命令時,要注意不要長時間使用

客戶端優化
避免多個應用使用一個Redis實例
不相干的業務拆分,公共數據作服務化
使用鏈接池

最大鏈接池的設置
maxIdle接近maxTotal便可
業務但願Redis達到的併發量
客戶端執行命令時間
Redis資源
資源開銷
例子:一次命令時間的平均耗時爲1ms,一個鏈接的QPS大約是1000
業務指望的QPS是50000
理論的maxTotal = 50000/1000 = 50個

2、內存優化

一、內存消耗
  • 內存使用統計
  • 內存消耗劃分
  • 子進程內存消耗

內存劃分:自身內存(800k左右),對象內存,緩存內存,Lua內存,內存碎片
內存消耗:自身內存,緩衝內存(客戶端緩衝器,複製緩衝區,AOF緩衝區),對象內存(key,value)
客戶端緩衝區

  • 普通客戶端

輸入緩衝區,最大1GB,超事後會被強制斷開,不可動態設置
輸出緩衝區配置 client-output-buffer-limit <class> <hard limiy> <soft limit> <soft seconds>
class客戶端類型,分爲三種 普通客戶端 slave從節點客戶端 pubsub發佈訂閱客戶端
hard limit 若是客戶端使用的輸出緩衝區大於 hard limit 客戶端會被當即關閉
soft limit和soft seconds 若是客戶端使用的輸出緩衝區超過了soft limit而且持續了soft seconds客戶端會被當即關閉

默認 client-output-buffer-limit normal 0 0 0
默認 沒有限制客戶端緩衝
注意 防止大的命令或者monitor
  • slave客戶端
默認 client-output-buffer-limit slave 256mb 64mb 60
阻塞 主從延遲較高,或者從節點過多
注意 主從網絡,從節點不要超過2個
  • pubsub客戶端
默認 client-output-buffer-limit pubsub 32mb 8mb 60
阻塞 生產大於消費
注意 根據實際場景適當調試

緩衝內存
複製緩衝區:此部份內存獨享,考慮部分複製,默認是1MB,能夠設置更大
AOF緩衝區:AOF重寫器鍵,AOF的緩衝區,沒有容量限制

對象內存
key:不要過長,量大不容忽視(redis3:embstr 39字節)
value:ziplist,intset等優化方式

內存碎片

必然存在 jemalloc
優化方式:
避免頻繁更新操做: append setrange等
安全重啓 例如redis sentinel和redis-cluster等

子進程內存消耗

必然存在 fork(bgsave和bgrewriteaof)
優化方式:
去掉THP特性
觀察寫入量

二、內存管理
  • 設置內存上限

定義實例最大內存,便於管理機器內存,通常預留30%

  • 動態調整內存上限

config set maxmemory 6GB
config rewrite

  • 內存回收策略

刪除過時鍵值

惰性刪除:訪問key->expired dict -> del key
定時刪除:每秒運行10次,採樣刪除

內存溢出
超過maxmemory後觸發響應策略,由maxmemory-policy控制

三、內存優化

內存分佈
自身內存,緩衝內存,對象內存
合理選擇數據結構
獨立統計:集合,MitMaps,HyperLogLog
客戶端內存優化
客戶端緩衝區
輸入緩衝區:最大1G
一次內存暴增 可能緣由:

  • 批量寫入
  • 主從不一致
  • 客戶端溢出

處理和預防:
找到對應的業務方直接幹掉
運維層面:線上Redis禁用monitor,適度限制緩衝區大小
開發層面:理解monitor的原理,也能夠短暫尋找熱點key,使用CacheCloud能夠直接監控到

四、Redis運維

Linux內核優化
overcommit含義:
0 表示內核將檢查是否由足夠的可用內存,若是有足夠的可用內存,內存申請經過,不然內存申請不經過,並把錯誤返回給應用進程
1 表示內核運行超量使用內存知道用完爲止
2 表示內核堅定不過兩的使用內存,即系統整個內存地址空間不超過swap+50%的RAM值,50%是overmit_ratio默認值,此參數一樣支持修改
獲取
cat /proc/sys/vm/overcommit_memory
設置
echo "vm.overcommit_memory=1" >> /etc/sysctl.conf
sysctl vm.overcommit_memory=1
最佳實踐:

  • Redis設置合理的maxmory,保證機器有20%-30%的閒置內存
  • 集中化管理AOF重寫的RDB的bgsave

swappiness最佳實踐

  • vm.swappiness=1

物理內存充足的時候,使Redis足夠快
物理內存不足的時候,避免Redis死掉

  • THP

做用:加速fork
建議:禁用,可能產生更大的內存消耗
設置方法:echo never > /sys/kernel/mm/transparent_hugepage/enabled

  • OOM killer

做用:內存使用超出,操做系統按照規則kill掉某些進程
配置方法:/proc/{progress_id}/oom_adj越小,被殺掉的機率越小
運維經驗:不要過分依賴此特性,應該合理管理內存

安全的Redis

被攻擊Redis的特徵:

  • redis所在的機器有外網IP
  • Redis以默認端口6379爲啓動端口,而且是對外網開放的
  • Redis是以root用戶啓動的
  • Redis沒有設置密碼
  • Redis的bind設置爲0.0.0.0或者""

攻擊方式:

  • flushall
  • set crakit id_rsa.pub
  • config set dir
  • config set dbfilename
  • save

安全七法則

  • 設置密碼:

服務端配置:requirepass和masterauth
客戶端鏈接:auth命令和-a參數
相關建議
密碼要足夠複雜,防止暴力破解
masterauth不要忘記
auth仍是經過銘文傳輸

  • 假裝危險命令

服務端配置:rename-command爲空或者隨機字符串
客戶端鏈接:不可用或者使用指定隨機字符串
相關建議
不支持config set 動態設置
RDB和AOF若是包含了rename-command以前的命令,將沒法使用
config命令自己是再Redis內核會使用到,不建議使用

  • bind

服務端配置:bind限制的是網卡,並非IP
相關建議
bind不支持 config set
bind 127.0.0.1須要謹慎

  • 防火牆:殺手鐗
  • 按期備份
  • 不使用默認端口,防止被若攻擊殺掉
  • 使用非root用戶啓動

熱點key

  • 客戶端
  • 代理端
  • 服務端
  • 機器蒐集
相關文章
相關標籤/搜索