這篇文章源于這里,大家還是多去看原文窥妇,
https://blog.csdn.net/BF02jgtRS00XKtCx/article/details/114384199?spm=1001.2101.3001.6650.15&utm_medium=distribute.pc_relevant.none-task-blog-2defaultOPENSEARCHRate-15-114384199-blog-123742395.pc_relevant_multi_platform_whitelistv3&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2defaultOPENSEARCHRate-15-114384199-blog-123742395.pc_relevant_multi_platform_whitelistv3&utm_relevant_index=19
1殉农、如何使用 Redis 更節(jié)省內(nèi)存析既?
首先笤虫,我們來看一下 Redis 內(nèi)存方面的優(yōu)化。
眾所周知陵珍,Redis 的性能之所以如此之高,原因就在于它的數(shù)據(jù)都存儲在「內(nèi)存」中违施,所以訪問 Redis 中的數(shù)據(jù)速度極快互纯。
但從資源利用率層面來說,機器的內(nèi)存資源相比于磁盤磕蒲,還是比較昂貴的留潦。
當(dāng)你的業(yè)務(wù)應(yīng)用在 Redis 中存儲數(shù)據(jù)很少時,你可能并不太關(guān)心內(nèi)存資源的使用情況辣往。但隨著業(yè)務(wù)的發(fā)展愤兵,你的業(yè)務(wù)存儲在 Redis 中的數(shù)據(jù)就會越來越多。
如果沒有提前制定好內(nèi)存優(yōu)化策略排吴,那么等業(yè)務(wù)開始增長時秆乳,Redis 占用的內(nèi)存也會開始膨脹。
所以钻哩,提前制定合理的內(nèi)存優(yōu)化策略屹堰,對于資源利用率的提升是很有必要的。
那在使用 Redis 時街氢,怎樣做才能更節(jié)省內(nèi)存呢扯键?這里我給你總結(jié)了 6 點建議,我們依次來看:
1) 控制 key 的長度
最簡單直接的內(nèi)存優(yōu)化珊肃,就是控制 key 的長度荣刑。
在開發(fā)業(yè)務(wù)時馅笙,你需要提前預(yù)估整個 Redis 中寫入 key 的數(shù)量,如果 key 數(shù)量達(dá)到了百萬級別厉亏,那么董习,過長的 key 名也會占用過多的內(nèi)存空間。
所以爱只,你需要保證 key 在簡單皿淋、清晰的前提下,盡可能把 key 定義得短一些恬试。
例如窝趣,原有的 key 為 user:book:123,則可以優(yōu)化為 u:bk:123训柴。
這樣一來哑舒,你的 Redis 就可以節(jié)省大量的內(nèi)存,這個方案對內(nèi)存的優(yōu)化非常直接和高效幻馁。
2) 避免存儲 bigkey
除了控制 key 的長度之外散址,你同樣需要關(guān)注 value 的大小,如果大量存儲 bigkey宣赔,也會導(dǎo)致 Redis 內(nèi)存增長過快悯辙。
除此之外熊咽,客戶端在讀寫 bigkey 時什燕,還有產(chǎn)生性能問題(下文會具體詳述)捺宗。
所以,你要避免在 Redis 中存儲 bigkey钩蚊,我給你的建議是:
String:大小控制在 10KB 以下
List/Hash/Set/ZSet:元素數(shù)量控制在 1 萬以下
3) 選擇合適的數(shù)據(jù)類型
Redis 提供了豐富的數(shù)據(jù)類型贡翘,這些數(shù)據(jù)類型在實現(xiàn)上,也對內(nèi)存使用做了優(yōu)化砰逻。具體來說就是鸣驱,一種數(shù)據(jù)類型對應(yīng)多種數(shù)據(jù)結(jié)構(gòu)來實現(xiàn):
例如,String蝠咆、Set 在存儲 int 數(shù)據(jù)時踊东,會采用整數(shù)編碼存儲。Hash刚操、ZSet 在元素數(shù)量比較少時(可配置)闸翅,會采用壓縮列表(ziplist)存儲,在存儲比較多的數(shù)據(jù)時菊霜,才會轉(zhuǎn)換為哈希表和跳表坚冀。
作者這么設(shè)計的原因,就是為了進(jìn)一步節(jié)約內(nèi)存資源鉴逞。
那么你在存儲數(shù)據(jù)時记某,就可以利用這些特性來優(yōu)化 Redis 的內(nèi)存司训。這里我給你的建議如下:
String、Set:盡可能存儲 int 類型數(shù)據(jù)
Hash液南、ZSet:存儲的元素數(shù)量控制在轉(zhuǎn)換閾值之下壳猜,以壓縮列表存儲,節(jié)約內(nèi)存
4) 把 Redis 當(dāng)作緩存使用贺拣,設(shè)置過期時間
Redis 數(shù)據(jù)存儲在內(nèi)存中蓖谢,這也意味著其資源是有限的捂蕴。你在使用 Redis 時譬涡,要把它當(dāng)做緩存來使用,而不是數(shù)據(jù)庫啥辨。
所以涡匀,你的應(yīng)用寫入到 Redis 中的數(shù)據(jù),盡可能地都設(shè)置「過期時間」溉知。
業(yè)務(wù)應(yīng)用在 Redis 中查不到數(shù)據(jù)時陨瘩,再從后端數(shù)據(jù)庫中加載到 Redis 中。
采用這種方案级乍,可以讓 Redis 中只保留經(jīng)常訪問的「熱數(shù)據(jù)」舌劳,內(nèi)存利用率也會比較高。
5) 實例設(shè)置 maxmemory + 淘汰策略
雖然你的 Redis key 都設(shè)置了過期時間玫荣,但如果你的業(yè)務(wù)應(yīng)用寫入量很大甚淡,并且過期時間設(shè)置得比較久,那么短期間內(nèi) Redis 的內(nèi)存依舊會快速增長捅厂。
如果不控制 Redis 的內(nèi)存上限贯卦,也會導(dǎo)致使用過多的內(nèi)存資源。
對于這種場景焙贷,你需要提前預(yù)估業(yè)務(wù)數(shù)據(jù)量撵割,然后給這個實例設(shè)置 maxmemory 控制實例的內(nèi)存上限,這樣可以避免 Redis 的內(nèi)存持續(xù)膨脹辙芍。
配置了 maxmemory啡彬,此時你還要設(shè)置數(shù)據(jù)淘汰策略,而淘汰策略如何選擇故硅,你需要結(jié)合你的業(yè)務(wù)特點來決定:
volatile-lru / allkeys-lru:優(yōu)先保留最近訪問過的數(shù)據(jù)
volatile-lfu / allkeys-lfu:優(yōu)先保留訪問次數(shù)最頻繁的數(shù)據(jù)(4.0+版本支持)
volatile-ttl :優(yōu)先淘汰即將過期的數(shù)據(jù)
volatile-random / allkeys-random:隨機淘汰數(shù)據(jù)
6) 數(shù)據(jù)壓縮后寫入 Redis
以上方案基本涵蓋了 Redis 內(nèi)存優(yōu)化的各個方面外遇。
如果你還想進(jìn)一步優(yōu)化 Redis 內(nèi)存,你還可以在業(yè)務(wù)應(yīng)用中先將數(shù)據(jù)壓縮契吉,再寫入到 Redis 中(例如采用 snappy跳仿、gzip 等壓縮算法)。
當(dāng)然捐晶,壓縮存儲的數(shù)據(jù)菲语,客戶端在讀取時還需要解壓縮妄辩,在這期間會消耗更多 CPU 資源,你需要根據(jù)實際情況進(jìn)行權(quán)衡山上。
以上就是「節(jié)省內(nèi)存資源」方面的實踐優(yōu)化眼耀,是不是都比較簡單?
2佩憾、如何持續(xù)發(fā)揮 Redis 的高性能哮伟?
當(dāng)你的系統(tǒng)決定引入 Redis 時,想必看中它最關(guān)鍵的一點就是:性能妄帘。
我們知道楞黄,一個單機版 Redis 就可以達(dá)到 10W QPS,這么高的性能抡驼,也意味著如果在使用過程中發(fā)生延遲情況鬼廓,就會與我們的預(yù)期不符。
所以致盟,在使用 Redis 時碎税,如何持續(xù)發(fā)揮它的高性能,避免操作延遲的情況發(fā)生馏锡,也是我們的關(guān)注焦點雷蹂。
在這方面,我給你總結(jié)了 13 條建議:
1) 避免存儲 bigkey
存儲 bigkey 除了前面講到的使用過多內(nèi)存之外杯道,對 Redis 性能也會有很大影響匪煌。
由于 Redis 處理請求是單線程的,當(dāng)你的應(yīng)用在寫入一個 bigkey 時蕉饼,更多時間將消耗在「內(nèi)存分配」上虐杯,這時操作延遲就會增加。同樣地昧港,刪除一個 bigkey 在「釋放內(nèi)存」時擎椰,也會發(fā)生耗時。
而且创肥,當(dāng)你在讀取這個 bigkey 時达舒,也會在「網(wǎng)絡(luò)數(shù)據(jù)傳輸」上花費更多時間,此時后面待執(zhí)行的請求就會發(fā)生排隊叹侄,Redis 性能下降巩搏。
所以,你的業(yè)務(wù)應(yīng)用盡量不要存儲 bigkey趾代,避免操作延遲發(fā)生贯底。
如果你確實有存儲 bigkey 的需求,你可以把 bigkey 拆分為多個小 key 存儲撒强。
2) 開啟 lazy-free 機制
如果你無法避免存儲 bigkey禽捆,那么我建議你開啟 Redis 的 lazy-free 機制笙什。(4.0+版本支持)
當(dāng)開啟這個機制后,Redis 在刪除一個 bigkey 時胚想,釋放內(nèi)存的耗時操作琐凭,將會放到后臺線程中去執(zhí)行,這樣可以在最大程度上浊服,避免對主線程的影響统屈。
3) 不使用復(fù)雜度過高的命令
Redis 是單線程模型處理請求,除了操作 bigkey 會導(dǎo)致后面請求發(fā)生排隊之外牙躺,在執(zhí)行復(fù)雜度過高的命令時愁憔,也會發(fā)生這種情況。
因為執(zhí)行復(fù)雜度過高的命令述呐,會消耗更多的 CPU 資源惩淳,主線程中的其它請求只能等待蕉毯,這時也會發(fā)生排隊延遲乓搬。
所以,你需要避免執(zhí)行例如 SORT代虾、SINTER进肯、SINTERSTORE、ZUNIONSTORE棉磨、ZINTERSTORE 等聚合類命令江掩。
對于這種聚合類操作,我建議你把它放到客戶端來執(zhí)行乘瓤,不要讓 Redis 承擔(dān)太多的計算工作环形。
4) 執(zhí)行 O(N) 命令時,關(guān)注 N 的大小
規(guī)避使用復(fù)雜度過高的命令衙傀,就可以高枕無憂了么抬吟?
答案是否定的。
當(dāng)你在執(zhí)行 O(N) 命令時统抬,同樣需要注意 N 的大小火本。
如果一次性查詢過多的數(shù)據(jù),也會在網(wǎng)絡(luò)傳輸過程中耗時過長聪建,操作延遲變大钙畔。
所以,對于容器類型(List/Hash/Set/ZSet)金麸,在元素數(shù)量未知的情況下擎析,一定不要無腦執(zhí)行 LRANGE key 0 -1 / HGETALL / SMEMBERS / ZRANGE key 0 -1。
在查詢數(shù)據(jù)時挥下,你要遵循以下原則:
先查詢數(shù)據(jù)元素的數(shù)量(LLEN/HLEN/SCARD/ZCARD)
元素數(shù)量較少揍魂,可一次性查詢?nèi)繑?shù)據(jù)
元素數(shù)量非常多挪鹏,分批查詢數(shù)據(jù)(LRANGE/HASCAN/SSCAN/ZSCAN)
5) 關(guān)注 DEL 時間復(fù)雜度
你沒看錯,在刪除一個 key 時愉烙,如果姿勢不對讨盒,也有可能影響到 Redis 性能。
刪除一個 key步责,我們通常使用的是 DEL 命令返顺,回想一下,你覺得 DEL 的時間復(fù)雜度是多少蔓肯?
O(1) 遂鹊?其實不一定。
當(dāng)你刪除的是一個 String 類型 key 時蔗包,時間復(fù)雜度確實是 O(1)秉扑。
但當(dāng)你要刪除的 key 是 List/Hash/Set/ZSet 類型,它的復(fù)雜度其實為 O(N)调限,N 代表元素個數(shù)舟陆。
也就是說,刪除一個 key耻矮,其元素數(shù)量越多秦躯,執(zhí)行 DEL 也就越慢!
原因在于裆装,刪除大量元素時踱承,需要依次回收每個元素的內(nèi)存,元素越多哨免,花費的時間也就越久茎活!
而且,這個過程默認(rèn)是在主線程中執(zhí)行的琢唾,這勢必會阻塞主線程载荔,產(chǎn)生性能問題。
那刪除這種元素比較多的 key慧耍,如何處理呢身辨?
我給你的建議是,分批刪除:
List類型:執(zhí)行多次 LPOP/RPOP芍碧,直到所有元素都刪除完成
Hash/Set/ZSet類型:先執(zhí)行 HSCAN/SSCAN/SCAN 查詢元素煌珊,再執(zhí)行 HDEL/SREM/ZREM 依次刪除每個元素
沒想到吧?一個小小的刪除操作泌豆,稍微不小心定庵,也有可能引發(fā)性能問題,你在操作時需要格外注意。
6) 批量命令代替單個命令
當(dāng)你需要一次性操作多個 key 時蔬浙,你應(yīng)該使用批量命令來處理猪落。
批量操作相比于多次單個操作的優(yōu)勢在于,可以顯著減少客戶端畴博、服務(wù)端的來回網(wǎng)絡(luò) IO 次數(shù)笨忌。
所以我給你的建議是:
String 使用 MGET/MSET 替代 GET/SET,
Hash 使用HMGET/HMSET 替代 HGET/HSET
其它數(shù)據(jù)類型使用 Pipeline俱病,打包一次性發(fā)送多個命令到服務(wù)端執(zhí)行
Redis(九):Pipeline(管道)VS Lua(腳本)
7) 避免集中過期 key
Redis 清理過期 key 是采用定時 + 懶惰的方式來做的官疲,而且這個過程都是在主線程中執(zhí)行。
如果你的業(yè)務(wù)存在大量 key 集中過期的情況亮隙,那么 Redis 在清理過期 key 時途凫,也會有阻塞主線程的風(fēng)險。
想要避免這種情況發(fā)生溢吻,你可以在設(shè)置過期時間時维费,增加一個隨機時間,把這些 key 的過期時間打散促王,從而降低集中過期對主線程的影響犀盟。
8) 使用長連接操作 Redis,合理配置連接池
你的業(yè)務(wù)應(yīng)該使用長連接操作 Redis硼砰,避免短連接且蓬。
當(dāng)使用短連接操作 Redis 時欣硼,每次都需要經(jīng)過 TCP 三次握手题翰、四次揮手,這個過程也會增加操作耗時诈胜。
同時豹障,你的客戶端應(yīng)該使用連接池的方式訪問 Redis,并設(shè)置合理的參數(shù)焦匈,長時間不操作 Redis 時血公,需及時釋放連接資源。
9) 只使用 db0
盡管 Redis 提供了 16 個 db缓熟,但我只建議你使用 db0累魔。
為什么呢?我總結(jié)了以下 3 點原因:
在一個連接上操作多個 db 數(shù)據(jù)時够滑,每次都需要先執(zhí)行 SELECT垦写,這會給 Redis 帶來額外的壓力
使用多個 db 的目的是,按不同業(yè)務(wù)線存儲數(shù)據(jù)彰触,那為何不拆分多個實例存儲呢梯投?拆分多個實例部署,多個業(yè)務(wù)線不會互相影響,還能提高 Redis 的訪問性能
Redis Cluster 只支持 db0分蓖,如果后期你想要遷移到 Redis Cluster尔艇,遷移成本高
10) 使用讀寫分離 + 分片集群
如果你的業(yè)務(wù)讀請求量很大,那么可以采用部署多個從庫的方式么鹤,實現(xiàn)讀寫分離终娃,讓 Redis 的從庫分擔(dān)讀壓力,進(jìn)而提升性能蒸甜。
如果你的業(yè)務(wù)寫請求量很大尝抖,單個 Redis 實例已無法支撐這么大的寫流量,那么此時你需要使用分片集群迅皇,分擔(dān)寫壓力昧辽。
11) 不開啟 AOF 或 AOF 配置為每秒刷盤
如果對于丟失數(shù)據(jù)不敏感的業(yè)務(wù),我建議你不開啟 AOF登颓,避免 AOF 寫磁盤拖慢 Redis 的性能搅荞。
如果確實需要開啟 AOF,那么我建議你配置為 appendfsync everysec框咙,把數(shù)據(jù)持久化的刷盤操作咕痛,放到后臺線程中去執(zhí)行,盡量降低 Redis 寫磁盤對性能的影響喇嘱。
12) 使用物理機部署 Redis
Redis 在做數(shù)據(jù)持久化時茉贡,采用創(chuàng)建子進(jìn)程的方式進(jìn)行。
而創(chuàng)建子進(jìn)程會調(diào)用操作系統(tǒng)的 fork 系統(tǒng)調(diào)用者铜,這個系統(tǒng)調(diào)用的執(zhí)行耗時腔丧,與系統(tǒng)環(huán)境有關(guān)。
虛擬機環(huán)境執(zhí)行 fork 的耗時作烟,要比物理機慢得多愉粤,所以你的 Redis 應(yīng)該盡可能部署在物理機上。
13) 關(guān)閉操作系統(tǒng)內(nèi)存大頁機制
Linux 操作系統(tǒng)提供了內(nèi)存大頁機制拿撩,其特點在于衣厘,每次應(yīng)用程序向操作系統(tǒng)申請內(nèi)存時,申請單位由之前的 4KB 變?yōu)榱?2MB压恒。
這會導(dǎo)致什么問題呢影暴?
當(dāng) Redis 在做數(shù)據(jù)持久化時,會先 fork 一個子進(jìn)程探赫,此時主進(jìn)程和子進(jìn)程共享相同的內(nèi)存地址空間型宙。
當(dāng)主進(jìn)程需要修改現(xiàn)有數(shù)據(jù)時,會采用寫時復(fù)制(Copy On Write)的方式進(jìn)行操作期吓,在這個過程中早歇,需要重新申請內(nèi)存倾芝。
如果申請內(nèi)存單位變?yōu)榱?2MB,那么勢必會增加內(nèi)存申請的耗時箭跳,如果此時主進(jìn)程有大量寫操作晨另,需要修改原有的數(shù)據(jù),那么在此期間谱姓,操作延遲就會變大借尿。
所以,為了避免出現(xiàn)這種問題屉来,你需要在操作系統(tǒng)上關(guān)閉內(nèi)存大頁機制路翻。
好了,以上這些就是 Redis 「高性能」方面的實踐優(yōu)化茄靠。如果你非常關(guān)心 Redis 的性能問題茂契,可以結(jié)合這些方面針對性優(yōu)化。
3慨绳、如何保證 Redis 的可靠性
這里我想提醒你的是掉冶,保證 Redis 可靠性其實并不難,但難的是如何做到「持續(xù)穩(wěn)定」脐雪。
下面我會從「資源隔離」厌小、「多副本」、「故障恢復(fù)」這三大維度战秋,帶你分析保障 Redis 可靠性的最佳實踐璧亚。
1) 按業(yè)務(wù)線部署實例
提升可靠性的第一步,就是「資源隔離」脂信。
你最好按不同的業(yè)務(wù)線來部署 Redis 實例癣蟋,這樣當(dāng)其中一個實例發(fā)生故障時,不會影響到其它業(yè)務(wù)吉嚣。
這種資源隔離的方案梢薪,實施成本是最低的,但成效卻是非常大的尝哆。
比如我們現(xiàn)在按照不同的業(yè)務(wù)不同的微服務(wù)劃分,部署了多套redis集群
2) 部署主從集群
如果你只使用單機版 Redis甜攀,那么就會存在機器宕機服務(wù)不可用的風(fēng)險秋泄。
所以,你需要部署「多副本」實例规阀,即主從集群恒序,這樣當(dāng)主庫宕機后,依舊有從庫可以使用谁撼,避免了數(shù)據(jù)丟失的風(fēng)險歧胁,也降低了服務(wù)不可用的時間。
在部署主從集群時,你還需要注意喊巍,主從庫需要分布在不同機器上屠缭,避免交叉部署。
這么做的原因在于崭参,通常情況下呵曹,Redis 的主庫會承擔(dān)所有的讀寫流量,所以我們一定要優(yōu)先保證主庫的穩(wěn)定性何暮,即使從庫機器異常奄喂,也不要對主庫造成影響。
而且海洼,有時我們需要對 Redis 做日常維護(hù)跨新,例如數(shù)據(jù)定時備份等操作,這時你就可以只在從庫上進(jìn)行坏逢,這只會消耗從庫機器的資源玻蝌,也避免了對主庫的影響。
3) 合理配置主從復(fù)制參數(shù)
在部署主從集群時词疼,如果參數(shù)配置不合理俯树,也有可能導(dǎo)致主從復(fù)制發(fā)生問題:
主從復(fù)制中斷
從庫發(fā)起全量復(fù)制,主庫性能受到影響
在這方面我給你的建議有以下 2 點:
設(shè)置合理的 repl-backlog 參數(shù):過小的 repl-backlog 在寫流量比較大的場景下贰盗,主從復(fù)制中斷會引發(fā)全量復(fù)制數(shù)據(jù)的風(fēng)險
設(shè)置合理的 slave client-output-buffer-limit:當(dāng)從庫復(fù)制發(fā)生問題時许饿,過小的 buffer 會導(dǎo)致從庫緩沖區(qū)溢出,從而導(dǎo)致復(fù)制中斷
4) 部署哨兵集群舵盈,實現(xiàn)故障自動切換
只部署了主從節(jié)點陋率,但故障發(fā)生時是無法自動切換的,所以秽晚,你還需要部署哨兵集群瓦糟,實現(xiàn)故障的「自動切換」。
而且赴蝇,多個哨兵節(jié)點需要分布在不同機器上菩浙,實例為奇數(shù)個,防止哨兵選舉失敗句伶,影響切換時間劲蜻。
以上這些就是保障 Redis「高可靠」實踐優(yōu)化,你應(yīng)該也發(fā)現(xiàn)了考余,這些都是部署和運維層的優(yōu)化先嬉。
除此之外,你可能還會對 Redis 做一些「日常運維」工作楚堤,這時你要注意哪些問題呢疫蔓?
4含懊、日常運維 Redis 需要注意什么
如果你是 DBA 運維人員,在平時運維 Redis 時衅胀,也需要注意以下 6 個方面岔乔。
1) 禁止使用 KEYS/FLUSHALL/FLUSHDB 命令
執(zhí)行這些命令,會長時間阻塞 Redis 主線程拗小,危害極大重罪,所以你必須禁止使用它。
如果確實想使用這些命令哀九,我給你的建議是:
SCAN 替換 KEYS
4.0+版本可使用 FLUSHALL/FLUSHDB ASYNC剿配,清空數(shù)據(jù)的操作放在后臺線程執(zhí)行
2) 掃描線上實例時,設(shè)置休眠時間
不管你是使用 SCAN 掃描線上實例阅束,還是對實例做 bigkey 統(tǒng)計分析呼胚,我建議你在掃描時一定記得設(shè)置休眠時間。
防止在掃描過程中息裸,實例 OPS 過高對 Redis 產(chǎn)生性能抖動蝇更。
3) 慎用 MONITOR 命令
有時在排查 Redis 問題時,你會使用 MONITOR 查看 Redis 正在執(zhí)行的命令呼盆。
但如果你的 Redis OPS 比較高年扩,那么在執(zhí)行 MONITOR 會導(dǎo)致 Redis 輸出緩沖區(qū)的內(nèi)存持續(xù)增長,這會嚴(yán)重消耗 Redis 的內(nèi)存資源访圃,甚至?xí)?dǎo)致實例內(nèi)存超過 maxmemory厨幻,引發(fā)數(shù)據(jù)淘汰,這種情況你需要格外注意腿时。
所以你在執(zhí)行 MONITOR 命令時况脆,一定要謹(jǐn)慎,盡量少用批糟。
4) 從庫必須設(shè)置為 slave-read-only
你的從庫必須設(shè)置為 slave-read-only 狀態(tài)格了,避免從庫寫入數(shù)據(jù),導(dǎo)致主從數(shù)據(jù)不一致徽鼎。
除此之外盛末,從庫如果是非 read-only 狀態(tài),如果你使用的是 4.0 以下的 Redis纬傲,它存在這樣的 Bug:
從庫寫入了有過期時間的數(shù)據(jù)满败,不會做定時清理和釋放內(nèi)存。
這會造成從庫的內(nèi)存泄露叹括!這個問題直到 4.0 版本才修復(fù),你在配置從庫時需要格外注意宵荒。
5) 合理配置 timeout 和 tcp-keepalive 參數(shù)
如果因為網(wǎng)絡(luò)原因汁雷,導(dǎo)致你的大量客戶端連接與 Redis 意外中斷净嘀,恰好你的 Redis 配置的 maxclients 參數(shù)比較小,此時有可能導(dǎo)致客戶端無法與服務(wù)端建立新的連接(服務(wù)端認(rèn)為超過了 maxclients)侠讯。
造成這個問題原因在于挖藏,客戶端與服務(wù)端每建立一個連接,Redis 都會給這個客戶端分配了一個 client fd厢漩。
當(dāng)客戶端與服務(wù)端網(wǎng)絡(luò)發(fā)生問題時膜眠,服務(wù)端并不會立即釋放這個 client fd。
什么時候釋放呢溜嗜?
Redis 內(nèi)部有一個定時任務(wù)宵膨,會定時檢測所有 client 的空閑時間是否超過配置的 timeout 值。
如果 Redis 沒有開啟 tcp-keepalive 的話炸宵,服務(wù)端直到配置的 timeout 時間后辟躏,才會清理釋放這個 client fd。
在沒有清理之前土全,如果還有大量新連接進(jìn)來捎琐,就有可能導(dǎo)致 Redis 服務(wù)端內(nèi)部持有的 client fd 超過了 maxclients,這時新連接就會被拒絕裹匙。
針對這種情況瑞凑,我給你的優(yōu)化建議是:
不要配置過高的 timeout:讓服務(wù)端盡快把無效的 client fd 清理掉
Redis 開啟 tcp-keepalive:這樣服務(wù)端會定時給客戶端發(fā)送 TCP 心跳包,檢測連接連通性概页,當(dāng)網(wǎng)絡(luò)異常時籽御,可以盡快清理僵尸 client fd
6) 調(diào)整 maxmemory 時,注意主從庫的調(diào)整順序
Redis 5.0 以下版本存在這樣一個問題:從庫內(nèi)存如果超過了 maxmemory绰沥,也會觸發(fā)數(shù)據(jù)淘汰篱蝇。
在某些場景下,從庫是可能優(yōu)先主庫達(dá)到 maxmemory 的(例如在從庫執(zhí)行 MONITOR 命令徽曲,輸出緩沖區(qū)占用大量內(nèi)存)零截,那么此時從庫開始淘汰數(shù)據(jù),主從庫就會產(chǎn)生不一致秃臣。
要想避免此問題涧衙,在調(diào)整 maxmemory 時,一定要注意主從庫的修改順序:
調(diào)大 maxmemory:先修改從庫奥此,再修改主庫
調(diào)小 maxmemory:先修改主庫弧哎,再修改從庫
直到 Redis 5.0,Redis 才增加了一個配置 replica-ignore-maxmemory稚虎,默認(rèn)從庫超過 maxmemory 不會淘汰數(shù)據(jù)撤嫩,才解決了此問題。
好了蠢终,以上這些就是「日常運維」Redis 需要注意的序攘,你可以對各個配置項查漏補缺茴她,看有哪些是需要優(yōu)化的。
接下來程奠,我們來看一下丈牢,保障 Redis「安全」都需要注意哪些問題。
5瞄沙、Redis 安全如何保證
無論如何己沛,在互聯(lián)網(wǎng)時代,安全問題一定是我們需要隨時警戒的距境。
你可能聽說過 Redis 被注入可執(zhí)行腳本申尼,然后拿到機器 root 權(quán)限的安全問題,都是因為在部署 Redis 時肮疗,沒有把安全風(fēng)險注意起來晶姊。
針對這方面,我給你的建議是:
不要把 Redis 部署在公網(wǎng)可訪問的服務(wù)器上
部署時不使用默認(rèn)端口 6379
以普通用戶啟動 Redis 進(jìn)程伪货,禁止 root 用戶啟動
限制 Redis 配置文件的目錄訪問權(quán)限
推薦開啟密碼認(rèn)證
禁用/重命名危險命令(KEYS/FLUSHALL/FLUSHDB/CONFIG/EVAL)
只要你把這些做到位们衙,基本上就可以保證 Redis 的安全風(fēng)險在可控范圍內(nèi)。
至此碱呼,我們分析了 Redis 在內(nèi)存蒙挑、性能、可靠性愚臀、日常運維方面的最佳實踐優(yōu)化忆蚀。
除了以上這些,你還需要做到提前「預(yù)防」姑裂。
如何預(yù)防 Redis 問題馋袜?
要想提前預(yù)防 Redis 問題,你需要做好以下兩個方面:
6舶斧、合理的資源規(guī)劃
先來說資源規(guī)劃欣鳖。
在部署 Redis 時,如果你可以提前做好資源規(guī)劃茴厉,可以避免很多因為資源不足產(chǎn)生的問題泽台。這方面我給你的建議有以下 3 點:
保證機器有足夠的 CPU、內(nèi)存矾缓、帶寬怀酷、磁盤資源
提前做好容量規(guī)劃,主庫機器預(yù)留一半內(nèi)存資源嗜闻,防止主從機器網(wǎng)絡(luò)故障蜕依,引發(fā)大面積全量同步,導(dǎo)致主庫機器內(nèi)存不足的問題
單個實例內(nèi)存建議控制在 10G 以下,大實例在主從全量同步笔横、RDB 備份時有阻塞風(fēng)險
再來看監(jiān)控如何做竞滓。
7咐吼、完善的監(jiān)控預(yù)警
監(jiān)控預(yù)警是提高穩(wěn)定性的重要環(huán)節(jié)吹缔,完善的監(jiān)控預(yù)警,可以把問題提前暴露出來锯茄,這樣我們才可以快速反應(yīng)厢塘,把問題最小化。
這方面我給你的建議是: