網(wǎng)站首頁(yè) 編程語(yǔ)言 正文
前言
Redis在項(xiàng)目中進(jìn)行廣泛使用,那么在日常的開(kāi)發(fā)過(guò)程中,我們?cè)谑褂肦edis的過(guò)程中需要注意那些呢?本文將從三個(gè)維度來(lái)講解如何進(jìn)行Redis的優(yōu)化。
內(nèi)存維度
控制key的長(zhǎng)度
key的一般都是采用字符串,而字符串的底層數(shù)據(jù)結(jié)構(gòu)為SDS,SDS 結(jié)構(gòu)中會(huì)包含字符串長(zhǎng)度、分配空間大小等元數(shù)據(jù)信息,當(dāng)key字符串的長(zhǎng)度增加時(shí),SDS中的元數(shù)據(jù)也會(huì)占用更多內(nèi)存空間,為了減少key的占用空間,我們可用根據(jù)業(yè)務(wù)名來(lái)使用相應(yīng)的英文縮寫(xiě)來(lái)表示。例如user用u表示,message 用m來(lái)表示。
避免存儲(chǔ)bigkey
我們既要注意key的長(zhǎng)度,同時(shí)也需要關(guān)注value的大小,Redis是使用單線程讀寫(xiě)數(shù)據(jù),bigkey 的讀寫(xiě)操作會(huì)阻塞線程,降低Redis的處理效率。
如何查詢bigkey
我們可以通過(guò)--bigkey的命令來(lái)查看Redis中所占用的bigkey的信息,具體的命令如下:
redis-cli -h 127.0.0.1 -p 6379 -a 'xxx' --bigkeys
從上述圖所示,我們可以查看到Redis中的key占用了32098個(gè)bytes,需要進(jìn)行相關(guān)優(yōu)化的。
建議:
- 如果key為string類型,建議value的存放值的大小為10KB左右。
- 如果key為L(zhǎng)ist/Hash/Set/ZSet類型,建議存放元素的的數(shù)量控制在1萬(wàn)以下。
選擇合適的數(shù)據(jù)類型
Redis提供了豐富的數(shù)據(jù)類型,對(duì)于存放的內(nèi)存也做了相關(guān)優(yōu)化。關(guān)乎數(shù)據(jù)結(jié)果的相關(guān)知識(shí),可以參考之前的文章。
例如:String和set在存儲(chǔ)int數(shù)據(jù)時(shí),會(huì)采用整數(shù)編碼存儲(chǔ)。Hash、ZSet在元素?cái)?shù)量比較少時(shí),會(huì)采用壓縮列表(ziplist)存儲(chǔ),在存儲(chǔ)比較多的數(shù)據(jù)時(shí),才會(huì)轉(zhuǎn)換為哈希表和跳表。
采用高效的序列化和壓縮方法
Redis中的字符串都是使用二進(jìn)制安全的字節(jié)數(shù)組來(lái)保存的,所以我們可以把業(yè)務(wù)的序列化成二進(jìn)制寫(xiě)入Redis,但是采用不同的序列化,所占用的空間大少不一樣。比如使用protostuff的序列化比java內(nèi)置的序列化效率更高,占用空間更少。針對(duì)json和xml數(shù)據(jù)格式的,可以采用gzip或者snappy算法對(duì)數(shù)據(jù)進(jìn)行壓縮存儲(chǔ),從而節(jié)省空間。
設(shè)置Redis最大內(nèi)存和淘汰策略
我們根據(jù)業(yè)務(wù)的數(shù)據(jù)量提前預(yù)估內(nèi)存大小,從而避免Redis的內(nèi)存持續(xù)膨脹,導(dǎo)致占用過(guò)多資源。
關(guān)于如何設(shè)置淘汰策略,需要集合實(shí)際的業(yè)務(wù)特性來(lái)選擇:
- volatile-lru / allkeys-lru:優(yōu)先保留最近訪問(wèn)過(guò)的數(shù)據(jù)
- volatile-lfu / allkeys-lfu:優(yōu)先保留訪問(wèn)次數(shù)最頻繁的數(shù)據(jù)
- volatile-ttl :優(yōu)先淘汰即將過(guò)期的數(shù)據(jù)
- volatile-random / allkeys-random:隨機(jī)淘汰數(shù)據(jù)
控制Redis實(shí)例的大小
Redis單實(shí)例的內(nèi)存大小建議設(shè)置在2~6GB之間。因?yàn)闊o(wú)論是RDB快照,還是主從集群進(jìn)行數(shù)據(jù)同步,都能很快完成,不會(huì)阻塞正常請(qǐng)求的處理。
定時(shí)清除內(nèi)存碎片
頻繁的新增修改會(huì)導(dǎo)致內(nèi)存碎片的增多,因此需要及時(shí)清理內(nèi)存碎片。
Redis提供了Info memory命令可以查看內(nèi)存使用信息,具體如下:
說(shuō)明:
- used_memory_rss是操作系統(tǒng)實(shí)際分配給 Redis的物理內(nèi)存空間。
- used_memory?是 Redis 為了保存數(shù)據(jù)實(shí)際申請(qǐng)使用的空間。
- mem_fragmentation_ratio=used_memory_rss/ used_memory
- mem_fragmentation_ratio 大于1但小于1.5。這種情況是合理的。
- mem_fragmentation_ratio大于1.5 這表明內(nèi)存碎片率已經(jīng)超過(guò)了50%。一般情況下,這個(gè)時(shí)候,我們就需要采取一些措施來(lái)降低內(nèi)存碎片率了。具體的內(nèi)存清理措施,將在后續(xù)的文章中進(jìn)行講解。
性能維度
禁止使用KEYS、FLUSHALL、FLUSHDB命令
- KEYS 按照key內(nèi)容進(jìn)行匹配,返回符合匹配條件的鍵值對(duì),該命令需要對(duì)Redis的全局哈希表進(jìn)行全表掃描,嚴(yán)重阻塞 Redis主線程。
- FLUSHALL 刪除Redis實(shí)例上的所有數(shù)據(jù),如果數(shù)據(jù)量很大,會(huì)嚴(yán)重阻塞Redis主線程。
- FLUSHDB,刪除當(dāng)前數(shù)據(jù)庫(kù)中的數(shù)據(jù),如果數(shù)據(jù)量很大,會(huì)阻塞Redis主線程。
優(yōu)化建議
我們需要在線上要禁用這些命令。具體的做法是,管理員采用rename-command命令在配置文件中對(duì)這些命令進(jìn)行重命名,讓客戶端無(wú)法使用這些命令。
慎用全量操作的命令
對(duì)于集合類型的來(lái)說(shuō),在未清楚集合數(shù)據(jù)大小的情況下,慎用查詢集合中的全量數(shù)據(jù),例如Hash的HetALL、Set的SMEMBERS命令、LRANGE key 0 -1 或者ZRANGE key 0 -1等命令,因?yàn)檫@些命令會(huì)對(duì)Hash或者Set類型的底層數(shù)據(jù)進(jìn)行全量掃描,當(dāng)集合數(shù)據(jù)量比較大時(shí),會(huì)阻塞Redis的主線程。
優(yōu)化建議:
當(dāng)元素?cái)?shù)據(jù)量較多時(shí),可以用SSCAN、HSCAN 命令分批返回集合中的數(shù)據(jù),減少對(duì)主線程的阻塞。
慎用復(fù)雜度過(guò)高命令
Redis執(zhí)行復(fù)雜度過(guò)高的命令,會(huì)消耗更多的 CPU 資源,導(dǎo)致主線程中的其它請(qǐng)求只能等待。常見(jiàn)的復(fù)雜命令如下:SORT、SINTER、SINTERSTORE、ZUNIONSTORE、ZINTERSTORE 等聚合類命令。
優(yōu)化建議:
當(dāng)需要執(zhí)行排序、交集、并集操作時(shí),可以在客戶端完成,避免讓Redis進(jìn)行過(guò)多計(jì)算,從而影響Redis性能。
設(shè)置合適的過(guò)期時(shí)間
Redis通常用于保存熱數(shù)據(jù)。熱數(shù)據(jù)一般都有使用的時(shí)效性。所以,在數(shù)據(jù)保存時(shí),根據(jù)業(yè)務(wù)使用數(shù)據(jù)的時(shí)長(zhǎng),合理的設(shè)置數(shù)據(jù)的過(guò)期時(shí)間。否則寫(xiě)入Redis的數(shù)據(jù)會(huì)一直占用內(nèi)存,如果數(shù)據(jù)持續(xù)增增長(zhǎng),會(huì)達(dá)到機(jī)器的內(nèi)存上限,造成內(nèi)存溢出,導(dǎo)致服務(wù)崩潰。
采用批量命令代替?zhèn)€命令
當(dāng)我們需要一次性操作多個(gè)key時(shí),可以使用批量命令來(lái)處理,批量命令可以減少客戶端與服務(wù)端的來(lái)回網(wǎng)絡(luò)IO次數(shù)。
- String或者Hash類型可以使用 MGET/MSET替代 GET/SET,HMGET/HMSET替代HGET/HSET
- 其它數(shù)據(jù)類型使用Pipeline命令,一次性打包發(fā)送多個(gè)命令到服務(wù)端執(zhí)行。
Pipeline具體使用:
redisTemplate.executePipelined(new RedisCallback<String>() {
@Override
public String doInRedis(RedisConnection connection) throws DataAccessException {
for (int i = 0; i < 5; i++)
{
connection.set(("test:" + i).getBytes(), "test".getBytes());
}
return null;
}
});
高可用維度
按照業(yè)務(wù)部署不同的實(shí)例
不同的業(yè)務(wù)線來(lái)部署 Redis 實(shí)例,這樣當(dāng)其中一個(gè)實(shí)例發(fā)生故障時(shí),不會(huì)影響到其它業(yè)務(wù)。
避免單點(diǎn)問(wèn)題
業(yè)務(wù)上根據(jù)實(shí)際情況采用主從、哨兵、集群方案,避免單點(diǎn)故障,影響業(yè)務(wù)的正常使用。
合理的設(shè)置相關(guān)參數(shù)
針對(duì)主從環(huán)境,我們需要合理設(shè)置相關(guān)參數(shù),具體內(nèi)容如下:
- 合理的設(shè)置repl-backlog參數(shù):如果repl-backlog設(shè)置過(guò)小,當(dāng)寫(xiě)流量比較大的場(chǎng)景下,主從復(fù)制中斷可能會(huì)引發(fā)全量復(fù)制數(shù)據(jù)的風(fēng)險(xiǎn)。
- 合理設(shè)置slave client-output-buffer-limit:當(dāng)從庫(kù)復(fù)制發(fā)生問(wèn)題時(shí),過(guò)小的 buffer會(huì)導(dǎo)致從庫(kù)緩沖區(qū)溢出,從而導(dǎo)致復(fù)制中斷。
總結(jié)
本文對(duì)于Redis的如何優(yōu)化從內(nèi)存、性能、高可用等三個(gè)維度進(jìn)行了詳細(xì)的講解,如有大家還有什么優(yōu)化建議歡迎提出,大家共同學(xué)習(xí),共同進(jìn)步。
原文鏈接:https://juejin.cn/post/7128419832927617054
相關(guān)推薦
- 2022-02-16 mac 使用launchctl 開(kāi)機(jī)時(shí)加速vim、emacs
- 2022-05-21 python?判斷文件或文件夾是否存在_python
- 2023-05-18 深入了解Android?Okio的超時(shí)機(jī)制_Android
- 2022-04-05 easyswoole轉(zhuǎn)發(fā)報(bào)錯(cuò) writev() failed (104 nginx
- 2023-11-12 ubuntu18.04 開(kāi)機(jī)后 USB 端口不能使用;臨時(shí)添加usb驅(qū)動(dòng)導(dǎo)致鼠標(biāo)鍵盤(pán)不可用ubunt
- 2022-04-28 WPF使用Canvas畫(huà)布面板布局_實(shí)用技巧
- 2022-05-20 SpringBoot整合Mybatis演示
- 2023-05-23 Numpy數(shù)組轉(zhuǎn)置的實(shí)現(xiàn)_python
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過(guò)濾器
- Spring Security概述快速入門(mén)
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡(jiǎn)單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支