真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

redis性能分析與優(yōu)化建議-創(chuàng)新互聯(lián)

首先,并不是說redis是內(nèi)存應(yīng)用就完全沒性能問題,用的不好,還是會出現(xiàn)各種狀況,例如RDB頻繁,碎片太多等.

10年積累的網(wǎng)站設(shè)計(jì)制作、成都網(wǎng)站制作經(jīng)驗(yàn),可以快速應(yīng)對客戶對網(wǎng)站的新想法和需求。提供各種問題對應(yīng)的解決方案。讓選擇我們的客戶得到更好、更有力的網(wǎng)絡(luò)服務(wù)。我雖然不認(rèn)識你,你也不認(rèn)識我。但先制作網(wǎng)站后付款的網(wǎng)站建設(shè)流程,更有海拉爾免費(fèi)網(wǎng)站建設(shè)讓你可以放心的選擇與我們合作。

性能分析

info信息:

在redis-cli進(jìn)入登錄界面后,輸入info all,或者redis-cli -h ${ip} -p ${post} -a "${pass}" -c info all,通常我們只輸入info就夠了,是簡介模式的意思,info all是詳細(xì)模式

之后,就會獲取所有與Redis服務(wù)相關(guān)的實(shí)時(shí)性能信息,類似于linux命令top那樣的東西.

info命令輸出的數(shù)據(jù)可分為10個(gè)類別,分別是:

  • server

  • clients

  • memory

  • persistence

  • stats

  • replication

  • cpu

  • commandstats

  • cluster

  • keyspace

下面展開解析一些重點(diǎn)信息.

server?部分:

redis_version?:???? Redis 服務(wù)器版本,不同版本會有些功能和命令不同

arch_bits?: ????架構(gòu)(32 或 64 位),某些情況,容易被忽略的坑

tcp_port?: ????TCP/IP 監(jiān)聽端口,確認(rèn)你操作的對不對

uptime_in_seconds?: ????自 Redis 服務(wù)器啟動以來,經(jīng)過的秒數(shù),可以確認(rèn)有沒有被重啟過

uptime_in_days?:???? 自 Redis 服務(wù)器啟動以來,經(jīng)過的天數(shù),可以確認(rèn)有沒有被重啟過

clients?部分:

connected_clients?: ????已連接客戶端的數(shù)量(不包括通過從屬服務(wù)器連接的客戶端)

client_longest_output_list?: ????當(dāng)前連接的客戶端當(dāng)中,最長的輸出列表

client_longest_input_buf?: ????當(dāng)前連接的客戶端當(dāng)中,大輸入緩存

blocked_clients?: ????正在等待阻塞命令(BLPOP、BRPOP、BRPOPLPUSH)的客戶端的數(shù)量

memory部分:

maxmemory/maxmemory_human:??? 配置文件redis.conf限制的可分配的大內(nèi)存總量,當(dāng)超過之后,就會觸發(fā)LRU刪除舊數(shù)據(jù).

used_memory/used_memory_human:??? 當(dāng)前redis-server實(shí)際使用的內(nèi)存總量,如果used_memory > maxmemory ,那么操作系統(tǒng)開始進(jìn)行內(nèi)存與swap空間交換,以便騰出新的物理內(nèi)存給新頁或活動頁(page)使用,那是有多糟糕大家可以想得到.

used_memory_rss/used_memory_rss_human:????從操作系統(tǒng)上顯示已經(jīng)分配的內(nèi)存總量,也就是這個(gè)redis-server占用的系統(tǒng)物理內(nèi)存實(shí)際值,比used_memory多出來的就可能是碎片.

mem_fragmentation_ratio:????內(nèi)存碎片率,內(nèi)存碎片率稍大于1是合理的,說明redis沒有發(fā)生內(nèi)存交換,如果內(nèi)存碎片率超過1.5,那就說明Redis消耗了實(shí)際需要物理內(nèi)存的150%,其中50%是內(nèi)存碎片率。若是內(nèi)存碎片率低于1的話,說明Redis內(nèi)存分配超出了物理內(nèi)存,操作系統(tǒng)正在進(jìn)行內(nèi)存交換。內(nèi)存交換會引起非常明顯的響應(yīng)延遲.

下面是計(jì)算公式:

redis性能分析與優(yōu)化建議

當(dāng)碎片率出現(xiàn)問題,有3種方法解決內(nèi)存管理變差的問題,提高redis性能:

1. 重啟Redis服務(wù)器:如果內(nèi)存碎片率超過1.5,重啟Redis服務(wù)器可以讓額外產(chǎn)生的內(nèi)存碎片失效并重新作為新內(nèi)存來使用,使操作系統(tǒng)恢復(fù)高效的內(nèi)存管理。

2.限制內(nèi)存交換:?如果內(nèi)存碎片率低于1,Redis實(shí)例可能會把部分?jǐn)?shù)據(jù)交換到硬盤上。內(nèi)存交換會嚴(yán)重影響Redis的性能,所以應(yīng)該增加可用物理內(nèi)存或減少實(shí)Redis內(nèi)存占用

3.修改內(nèi)存分配器:
Redis支持glibc’s malloc、jemalloc11、tcmalloc幾種不同的內(nèi)存分配器,每個(gè)分配器在內(nèi)存分配和碎片上都有不同的實(shí)現(xiàn)。不建議普通管理員修改Redis默認(rèn)內(nèi)存分配器,因?yàn)檫@需要完全理解這幾種內(nèi)存分配器的差異,也要重新編譯Redis。

used_memory_lua:????Lua腳本引擎所使用的內(nèi)存大小。redis默認(rèn)允許使用lua腳本,不過太多了的話就占用了可用內(nèi)存

mem_allocator:????在編譯時(shí)指定的Redis使用的內(nèi)存分配器,可以是libc、jemalloc、tcmalloc.

persistence?部分:

RDB信息,RDB的操作要用到bgsave命令,是比較耗費(fèi)資源的持久化操作,而且不是實(shí)時(shí)的,容易造成宕機(jī)數(shù)據(jù)消失,如果內(nèi)存容量滿了,不能做bgsave操作的話,隱患會很大.

rdb_changes_since_last_save?: ????距離最近一次成功創(chuàng)建持久化文件之后,經(jīng)過了多少秒。持久化是需要占用資源的,在高負(fù)載下需要盡量避免持久化的影響,下列參數(shù)均有參考價(jià)值.

rdb_bgsave_in_progress:????當(dāng)前是否在進(jìn)行bgsave操作。是為1

rdb_last_save_time?:???? 最近一次成功創(chuàng)建 RDB 文件的 UNIX 時(shí)間戳。

rdb_last_bgsave_time_sec?: ????記錄了最近一次創(chuàng)建 RDB 文件耗費(fèi)的秒數(shù)。

rdb_last_bgsave_status:????上次保存的狀態(tài)

rdb_current_bgsave_time_sec?: ????如果服務(wù)器正在創(chuàng)建 RDB 文件,那么這個(gè)域記錄的就是當(dāng)前的創(chuàng)建操作已經(jīng)耗費(fèi)的秒數(shù)。

AOF信息,AOF是持續(xù)記錄命令到持久化文件的方法,比較節(jié)省資源,但是AOF存儲文件會沒有限制存儲,時(shí)間一長,或者操作太頻繁,那就會出現(xiàn)AOF文件過大,撐爆硬盤的事.而且,這個(gè)方法還是會定期bgsave操作.

aof_enabled:????AOF文件是否啟用

aof_rewrite_in_progress:????表示當(dāng)前是否在進(jìn)行寫入AOF文件操作

aof_last_rewrite_time_sec?: ????最近一次創(chuàng)建 AOF 文件耗費(fèi)的時(shí)長。

aof_current_rewrite_time_sec?: ????如果服務(wù)器正在創(chuàng)建 AOF 文件,那么這個(gè)域記錄的就是當(dāng)前的創(chuàng)建操作已經(jīng)耗費(fèi)的秒數(shù)。

aof_last_bgrewrite_status:????上次寫入狀態(tài)

aof_last_write_status:????上次寫入狀態(tài)

aof_base_size?: ????服務(wù)器啟動時(shí)或者 AOF 重寫最近一次執(zhí)行之后,AOF 文件的大小。

aof_pending_bio_fsync?: ????后臺 I/O 隊(duì)列里面,等待執(zhí)行的?fsync?調(diào)用數(shù)量。

aof_delayed_fsync?: ????被延遲的?fsync?調(diào)用數(shù)量。

stats部分:

total_commands_processed:????顯示了Redis服務(wù)處理命令的總數(shù),且值是遞增的.因?yàn)镽edis是個(gè)單線程模型,客戶端過來的命令是按照順序執(zhí)行的,如果命令隊(duì)列里等待處理的命令數(shù)量比較多,命令的響應(yīng)時(shí)間就變慢,甚至于后面的命令完全被阻塞,導(dǎo)致Redis性能降低.所以這個(gè)時(shí)候就需要記錄這個(gè)參數(shù)的值,是不是增長過快,導(dǎo)致了性能降低.

instantaneous_ops_per_sec?:???? 服務(wù)器每秒鐘執(zhí)行的命令數(shù)量,同上,如果增長過快就有問題。

expired_keys?:???? 因?yàn)檫^期而被自動刪除的數(shù)據(jù)庫鍵數(shù)量,具有參考意義。

evicted_keys:????顯示因?yàn)閙axmemory限制導(dǎo)致key被回收刪除的數(shù)量.根據(jù)配置文件中設(shè)置maxmemory-policy值來確定Redis是使用lru策略還是過期時(shí)間策略.如果是過期回收的,不會被記錄在這里,通常這個(gè)值不為0,那就要考慮增加內(nèi)存限制,不然就會造成內(nèi)存交換,輕則性能變差,重則丟數(shù)據(jù).

latest_fork_usec:???? 最近一次?fork()?操作耗費(fèi)的微秒數(shù)。fork()是很耗費(fèi)資源的操作,所以要留意一下.

commandstats部分:

cmdstat_XXX:????記錄了各種不同類型的命令的執(zhí)行統(tǒng)計(jì)信息,命令包含有讀有寫,分得比較細(xì),其中calls代表命令執(zhí)行的次數(shù),usec代表命令耗費(fèi)的 CPU 時(shí)間,usec_per_call代表每個(gè)命令耗費(fèi)的平均 CPU 時(shí)間,單位為微秒.對于排錯(cuò)有一定用途.

---------------------------------------------------------------------------------------------------

其他問題的分析方法:

查看redis的網(wǎng)絡(luò)延時(shí):

Redis的延遲數(shù)據(jù)是無法從info信息中獲取的。倘若想要查看延遲時(shí)間,可以用 Redis-cli工具加--latency參數(shù)運(yùn)行

redis-cli --latency -h 10.1.2.11 -p 6379

他將會持續(xù)掃描延遲時(shí)間,直到按ctrl+C退出,以毫秒為單位測量Redis的響應(yīng)延遲時(shí)間,由于服務(wù)器不同的運(yùn)行情況,延遲時(shí)間可能有所誤差,通常1G網(wǎng)卡的延遲時(shí)間是0.2毫秒,若延時(shí)值遠(yuǎn)高于這個(gè)參考值,那明顯是有性能問題了。這個(gè)時(shí)候我們要考慮檢查一下網(wǎng)絡(luò)狀況.

查看redis的慢查詢:

Slow log 是 Redis 用來記錄查詢執(zhí)行時(shí)間的日志系統(tǒng)。Redis中的slowlog命令可以讓我們快速定位到那些超出指定執(zhí)行時(shí)間的慢命令,默認(rèn)情況下會記錄執(zhí)行時(shí)間超過10ms的記錄到日志,由參數(shù)slowlog-log-slower-than控制.最多記錄128條,由參數(shù)slowlog-max-len控制,超過就自動刪除.

通常這個(gè)默認(rèn)參數(shù)夠用,也可以在線CONFIG SET修改參數(shù)slowlog-log-slower-than和slowlog-max-len來修改這個(gè)時(shí)間和限制條數(shù)。

通常1gb帶寬的網(wǎng)絡(luò)延遲,預(yù)期在0.2ms左右,倘若一個(gè)命令僅執(zhí)行時(shí)間就超過10ms,那比網(wǎng)絡(luò)延遲慢了近50倍。可以通過使用Redis-cli工具,輸入slowlog get命令查看,返回結(jié)果的第三個(gè)字段以微妙位單位顯示命令的執(zhí)行時(shí)間。假如只需要查看最后3個(gè)慢命令,輸入slowlog get 10即可。

127.0.0.1:6379>?slowlog?get?10
????.
????.
????.
4)?1)?(integer)?215
????2)?(integer)?1489099695
????3)?(integer)?11983
????4)?1)?"SADD"
???????2)?"USER_TOKEN_MAP51193"
???????3)?"qIzwZKBmBJozKprQgoTEI3Qo8QO2Fi!4"
?5)?1)?(integer)?214
????2)?(integer)?1489087112
????3)?(integer)?18002
????4)?1)?"SADD"
???????2)?"USER_TOKEN_MAP51192"
???????3)?"Z3Hs!iTUNfweqvLLf!ptdchSV2JAOrrH"
?6)?1)?(integer)?213
????2)?(integer)?1489069123
????3)?(integer)?15407
????4)?1)?"SADD"
???????2)?"USER_TOKEN_MAP51191"
???????3)?"S3rNzOBwUlaI3QfOK9dIITB6Bk7LIGYe"

  • 1=日志的唯一標(biāo)識符

  • 2=被記錄命令的執(zhí)行時(shí)間點(diǎn),以 UNIX 時(shí)間戳格式表示

  • 3=查詢執(zhí)行時(shí)間,以微秒為單位。例子中命令使用11毫秒。

  • 4= 執(zhí)行的命令,以數(shù)組的形式排列。完整命令是拼在一起.

監(jiān)控客戶端的連接:

因?yàn)镽edis是單線程模型(只能使用單核),來處理所有客戶端的請求, 但由于客戶端連接數(shù)的增長,處理請求的線程資源開始降低分配給單個(gè)客戶端連接的處理時(shí)間,這時(shí)每個(gè)客戶端需要花費(fèi)更多的時(shí)間去等待Redis共享服務(wù)的響應(yīng)。

#查看客戶端連接狀態(tài)
127.0.0.1:6379>?info?clients
#?Clients
connected_clients:11
client_longest_output_list:0
client_biggest_input_buf:0
blocked_clients:0

第一個(gè)字段(connected_clients)顯示當(dāng)前實(shí)例客戶端連接的總數(shù),Redis默認(rèn)允許客戶端連接的大數(shù)量是10000。若是看到連接數(shù)超過5000以上,那可能會影響Redis的性能。倘若一些或大部分客戶端發(fā)送大量的命令過來,這個(gè)數(shù)字會低的多。

查當(dāng)前客戶端狀態(tài)

#查看所有正在連接的客戶端狀態(tài),
127.0.0.1:6379>?client?list
id=821882?addr=10.25.138.2:60990?fd=8?name=?age=53838?idle=24?flags=N?db=0?sub=0?psub=0?multi=-1?qbuf=0?qbuf-free=0?obl=0?oll=0?omem=0?events=r?cmd=ping

這個(gè)看起來有點(diǎn)繞,因?yàn)楹蜌v史數(shù)據(jù)是混在一起的:

addr:客戶端的地址和端口,包含當(dāng)前連接和歷史連接

age:這個(gè)客戶端連進(jìn)來的生命周期,也就是連進(jìn)來之后的持續(xù)時(shí)間,單位是秒

idle:這個(gè)客戶端的空閑時(shí)間,也就是說這個(gè)時(shí)間內(nèi),客戶端沒有操作,單位是秒

db:操作的數(shù)據(jù)庫,redis默認(rèn)有db0~db15可用選擇

cmd:客戶端最后一次使用的命令

也就是說,idle越少,那就代表這個(gè)客戶端剛剛操作,反則是歷史記錄而已.age越少就代表是剛剛建立的連接,越大則是歷史連接.而有些時(shí)候個(gè)別使用者用了scan或keys命令,會對數(shù)據(jù)量大的redis造成很大的負(fù)載壓力,所以需要特別關(guān)注.

特大key的統(tǒng)計(jì):

在redis的單線程處理方式下,一些數(shù)據(jù)量比較大的key的操作明顯是會影響性能,所以必要時(shí),我們要統(tǒng)計(jì)出來,交給開發(fā)來優(yōu)化

#統(tǒng)計(jì)生產(chǎn)上比較大的key
redis-cli?-h*?-a*?-p*?--bigkeys
#查看某個(gè)key的持續(xù)時(shí)間
127.0.0.1:6379>?OBJECT?IDLETIME?key名字

--bigkeys信息解析:

1.該命令使用scan方式對key進(jìn)行統(tǒng)計(jì),所以使用時(shí)無需擔(dān)心對redis造成阻塞。
2.輸出大概分為兩部分,summary之上的部分,只是顯示了掃描的過程。summary部分給出了每種數(shù)據(jù)結(jié)構(gòu)中大的Key,所以下面部分更重要些。
3.統(tǒng)計(jì)出的大key只有string類型是以字節(jié)長度為衡量標(biāo)準(zhǔn)的。list,set,zset等都是以元素個(gè)數(shù)作為衡量標(biāo)準(zhǔn),不能說明其占的內(nèi)存就一定多,需要另外計(jì)算。

得出大key名字后,就去看看粗略大小,

#查看某個(gè)key序列化后的長度
debug?object?key

輸出的項(xiàng)的說明:

  • Value at:key的內(nèi)存地址

  • refcount:引用次數(shù)

  • encoding:編碼類型

  • serializedlength:經(jīng)過壓縮后的序列化長度,單位是 B, 也就是 Byte(字節(jié)),因?yàn)閴嚎s效果要看編碼類型,不一定反應(yīng)內(nèi)存中的大小,只是有參考價(jià)值.

  • lru_seconds_idle:空閑時(shí)間

終上所述,我們要關(guān)注的大key信息正是serializedlength的長度了.

另外還有一個(gè)工具[rdbtools],可以全面分析redis里面的key信息,但是要額外安裝,對于內(nèi)網(wǎng)用戶不可謂不麻煩,因?yàn)椴皇窍到y(tǒng)自帶的功能,這里不詳細(xì)說明,請等待另一篇文章另外介紹.

數(shù)據(jù)持久化引發(fā)的延遲

Redis的數(shù)據(jù)持久化工作本身就會帶來延遲,需要根據(jù)數(shù)據(jù)的安全級別和性能要求制定合理的持久化策略:

1.AOF + fsync always的設(shè)置雖然能夠絕對確保數(shù)據(jù)安全,但每個(gè)操作都會觸發(fā)一次fsync,會對Redis的性能有比較明顯的影響
2.AOF + fsync every second是比較好的折中方案,每秒fsync一次
3.AOF + fsync never會提供AOF持久化方案下的最優(yōu)性能,使用RDB持久化通常會提供比使用AOF更高的性能,但需要注意RDB的策略配置
4.每一次RDB快照和AOF Rewrite都需要Redis主進(jìn)程進(jìn)行fork操作。fork操作本身可能會產(chǎn)生較高的耗時(shí),與CPU和Redis占用的內(nèi)存大小有關(guān)。根據(jù)具體的情況合理配置RDB快照和AOF Rewrite時(shí)機(jī),避免過于頻繁的fork帶來的延遲.
例如:Redis在fork子進(jìn)程時(shí)需要將內(nèi)存分頁表拷貝至子進(jìn)程,以占用了24GB內(nèi)存的Redis實(shí)例為例,共需要拷貝24GB / 4kB * 8 = 48MB的數(shù)據(jù)。在使用單Xeon 2.27Ghz的物理機(jī)上,這一fork操作耗時(shí)216ms。

可以通過INFO命令返回的latest_fork_usec字段查看上一次fork操作的耗時(shí)(微秒)。

Swap引發(fā)的延遲

當(dāng)Linux將Redis所用的內(nèi)存分頁移至swap空間時(shí),將會阻塞Redis進(jìn)程,導(dǎo)致Redis出現(xiàn)不正常的延遲。Swap通常在物理內(nèi)存不足或一些進(jìn)程在進(jìn)行大量I/O操作時(shí)發(fā)生,應(yīng)盡可能避免上述兩種情況的出現(xiàn)。

在/proc/redis進(jìn)程號/smaps文件中會保存進(jìn)程的swap記錄,通過查看這個(gè)文件,能夠判斷Redis的延遲是否由Swap產(chǎn)生。如果這個(gè)文件中記錄了較大的Swap size,則說明延遲很有可能是Swap造成的。

例子如下,可以看到當(dāng)前swap的狀態(tài)時(shí)0KB,也就是沒用到swap,

#/proc/pid/smaps顯示了進(jìn)程運(yùn)行時(shí)的內(nèi)存影響,系統(tǒng)的運(yùn)行時(shí)庫(so),堆,棧信息均可在其中看到。
cat?/proc/`ps?aux?|grep?redis?|grep?-v?grep?|awk?'{print?$2}'`/smaps
00400000-00531000?r-xp?00000000?fc:02?805438521?/usr/local/bin/redis-server
Size:???????????????1220?kB
Rss:?????????????????924?kB
Pss:?????????????????924?kB
Shared_Clean:??????????0?kB
Shared_Dirty:??????????0?kB
Private_Clean:???????924?kB
Private_Dirty:?????????0?kB
Referenced:??????????924?kB
Anonymous:?????????????0?kB
AnonHugePages:?????????0?kB
Shared_Hugetlb:????????0?kB
Private_Hugetlb:???????0?kB
Swap:??????????????????0?kB
SwapPss:???????????????0?kB
KernelPageSize:????????4?kB
MMUPageSize:???????????4?kB
Locked:????????????????0?kB

內(nèi)存滿了怎么辦:
redis內(nèi)存滿了,那確實(shí)是很麻煩的事,但是再麻煩也得處理啊,這就得從redis架構(gòu)原理說起了.
首先我們要了解,redis的內(nèi)存滿,并不代表是用了系統(tǒng)的100%內(nèi)存,為什么這么說呢?我們都知道redis做持久化是save和bgsave,而常用的bgsave(也是默認(rèn))是fork一個(gè)進(jìn)程,把內(nèi)存copy一份再壓縮后存到硬盤成*.rdb文件.這里就涉及一個(gè)問題,你內(nèi)存必須保證有和數(shù)據(jù)一樣大的空間才能做bgsave,那嚴(yán)格來說,只要你的內(nèi)存超過系統(tǒng)內(nèi)存的50%,那就可以被稱為redis內(nèi)存滿了.
redis的持久化策略,上面只說了持久化會阻塞操作導(dǎo)致延時(shí),而如果內(nèi)存滿了,數(shù)據(jù)量的增加會讓持久化造成的延時(shí)會更嚴(yán)重,而且持久化失敗后是默認(rèn)每分鐘重試一遍.
那么問題就來了,因?yàn)閮?nèi)存滿了,持久化失敗,然后一分鐘后再持久化,就造成了惡性循環(huán),redis的性能直線下降.那怎么辦好呢?
更改持久化策略是個(gè)臨時(shí)解決方案,

可以先嘗試關(guān)閉持久化失敗導(dǎo)致的終止所有的客戶端write請求的選項(xiàng),

config?set?stop-writes-on-bgsave-error?no

但是這個(gè)方法治標(biāo)不治本,我們只是忽略了問題而已,

另一種解決方案就是直接把rdb持久化關(guān)閉掉:

config?set?save?""

為什么能解決,答案也很明顯,關(guān)閉了持久化,那就不會阻塞操作,那你redis的性能還是保證到了.但是又會引入新問題,沒了持久化,內(nèi)存數(shù)據(jù)如果redis-server程序重啟或關(guān)閉就沒了,還是比較危險(xiǎn)的.而且內(nèi)存滿的問題還在,如果內(nèi)存用到了系統(tǒng)內(nèi)存100%,甚至觸發(fā)了系統(tǒng)的OOM,那就坑大了,因?yàn)閮?nèi)存被徹底清空,數(shù)據(jù)也都沒有了.也就是所謂的臨時(shí)解決辦法.
所以正確的做法是,在不阻塞操作之后,刪掉可以刪除的數(shù)據(jù),再重新拉起持久化,然后準(zhǔn)備擴(kuò)容的工作.
占用內(nèi)存看哪里,上面已經(jīng)說了,但是內(nèi)存滿了的定義,并不一定只是實(shí)際內(nèi)存占用,碎片也是要包含在內(nèi)的,例如:

#這種情況,肯定就是內(nèi)存滿
used_memory_human:4.2G
maxmemory_human:4.00G
#但是這種情況,也是內(nèi)存滿
used_memory_human:792.30M
used_memory_rss_human:3.97G
used_memory_peak_human:4.10G
maxmemory_human:4.00G

因?yàn)閮?nèi)存碎片沒有被釋放,那它還是會占用內(nèi)存空間,對于系統(tǒng)來說,碎片也是redis-server占用的內(nèi)存,不是空閑的內(nèi)存,那剩下的內(nèi)存還是不足以用來bgsave.那怎么解決碎片呢?

在redis4.0之前,沒其他更好辦法,只能重啟redis-server,之后的新版本則新加了一個(gè)碎片回收參數(shù),杜絕了這個(gè)問題.

而碎片問題其實(shí)影響頗大,因?yàn)檎G闆r下,這些用不了又確實(shí)占著內(nèi)存的數(shù)據(jù),會讓我們的redis浪費(fèi)空間之余,還會額外造成內(nèi)存滿的風(fēng)險(xiǎn).所以也正如上面說的那樣,如果碎片率超過1.5之后,是該想想回收一下.

那確實(shí)需要保存內(nèi)存數(shù)據(jù)怎么辦?只能忍痛割愛,把不必要的數(shù)據(jù)刪除掉,讓內(nèi)存降到能做bgsave之后再重啟來回收碎片.要不,就是升級到4.0之后避免同類問題.

優(yōu)化建議

系統(tǒng)優(yōu)化

1.關(guān)閉Transparent huge pages

Transparent HugePages會讓內(nèi)核khugepaged線程在運(yùn)行時(shí)動態(tài)分配內(nèi)存。在大部分linux發(fā)行版本中默認(rèn)是啟用的,缺點(diǎn)是可能會造成內(nèi)存在運(yùn)行時(shí)的延遲分配,對于大內(nèi)存應(yīng)用并不友好,例如:oracle,redis等會占用大量內(nèi)存的應(yīng)用,所以建議關(guān)閉。

#關(guān)閉Transparent?HugePages,默認(rèn)狀態(tài)是[always]
echo?never?>?/sys/kernel/mm/transparent_hugepage/enabled

2.在物理機(jī)部署redis,這點(diǎn)不用多說了,虛擬機(jī)或者是docker都會有一定的延時(shí),沒有必要為了好管理二浪費(fèi)這些性能。

3.多用連接池,而不是頻繁斷開再連接,效果我想不言而喻。

4.客戶端進(jìn)行的批量數(shù)據(jù)操作,應(yīng)使用Pipeline特性在一次交互中完成。

行為優(yōu)化

1.假如緩存數(shù)據(jù)小于4GB,可以選擇使用32位的Redis實(shí)例。因?yàn)?2位實(shí)例上的指針大小只有64位的一半,它的內(nèi)存空間占用空間會更少些。Redis的dump文件在32位和64位之間是互相兼容的, 因此倘若有減少占用內(nèi)存空間的需求,可以嘗試先使用32位,后面再切換到64位上。

2.盡可能的使用Hash數(shù)據(jù)結(jié)構(gòu)。因?yàn)镽edis在儲存小于100個(gè)字段的Hash結(jié)構(gòu)上,其存儲效率是非常高的。所以在不需要集合(set)操作或list的push/pop操作的時(shí)候,盡可能的使用Hash結(jié)構(gòu)。Hash結(jié)構(gòu)的操作命令是HSET(key, fields, value)和HGET(key, field),使用它可以存儲或從Hash中取出指定的字段。

3.盡量設(shè)置key的過期時(shí)間。一個(gè)減少內(nèi)存使用率的簡單方法就是,每當(dāng)存儲對象時(shí)確保設(shè)置key的過期時(shí)間。倘若key在明確的時(shí)間周期內(nèi)使用或者舊key不大可能被使用時(shí),就可以用Redis過期時(shí)間命令(expire,expireat, pexpire, pexpireat)去設(shè)置過期時(shí)間,這樣Redis會在key過期時(shí)自動刪除key.用ttl命令可以查詢過期時(shí)間,單位是秒,顯示-2代表key不存在,顯示-1代表沒有設(shè)置超時(shí)時(shí)間(也就是永久的).

4.使用多參數(shù)命令:若是客戶端在很短的時(shí)間內(nèi)發(fā)送大量的命令過來,會發(fā)現(xiàn)響應(yīng)時(shí)間明顯變慢,這由于后面命令一直在等待隊(duì)列中前面大量命令執(zhí)行完畢。舉例來說,循環(huán)使用LSET命令去添加1000個(gè)元素到list結(jié)構(gòu)中,是性能比較差的一種方式,更好的做法是在客戶端創(chuàng)建一個(gè)1000元素的列表,用單個(gè)命令LPUSH或RPUSH,通過多參數(shù)構(gòu)造形式一次性把1000個(gè)元素發(fā)送的Redis服務(wù)上。

5.管道命令:另一個(gè)減少多命令的方法是使用管道(pipeline),把幾個(gè)命令合并一起執(zhí)行,從而減少因網(wǎng)絡(luò)開銷引起的延遲問題。因?yàn)?0個(gè)命令單獨(dú)發(fā)送到服務(wù)端會引起10次網(wǎng)絡(luò)延遲開銷,使用管道會一次性把執(zhí)行結(jié)果返回,僅需要一次網(wǎng)絡(luò)延遲開銷。Redis本身支持管道命令,大多數(shù)客戶端也支持,倘若當(dāng)前實(shí)例延遲很明顯,那么使用管道去降低延遲是非常有效的。

6.避免操作大集合的慢命令:如果命令處理頻率過低導(dǎo)致延遲時(shí)間增加,這可能是因?yàn)槭褂昧烁邥r(shí)間復(fù)雜度的命令操作導(dǎo)致,這意味著每個(gè)命令從集合中獲取數(shù)據(jù)的時(shí)間增大。 所以減少使用高時(shí)間復(fù)雜的命令,能顯著的提高的Redis的性能。

7.限制客戶端連接數(shù):自Redis2.6以后,允許使用者在配置文件(Redis.conf)maxclients屬性上修改客戶端連接的大數(shù),也可以通過在Redis-cli工具上輸入config set maxclients 去設(shè)置大連接數(shù)。根據(jù)連接數(shù)負(fù)載的情況,這個(gè)數(shù)字應(yīng)該設(shè)置為預(yù)期連接數(shù)峰值的110%到150之間,若是連接數(shù)超出這個(gè)數(shù)字后,Redis會拒絕并立刻關(guān)閉新來的連接。通過設(shè)置大連接數(shù)來限制非預(yù)期數(shù)量的連接數(shù)增長,是非常重要的。另外,新連接嘗試失敗會返回一個(gè)錯(cuò)誤消息,這可以讓客戶端知道,Redis此時(shí)有非預(yù)期數(shù)量的連接數(shù),以便執(zhí)行對應(yīng)的處理措施。 上述二種做法對控制連接數(shù)的數(shù)量和持續(xù)保持Redis的性能最優(yōu)是非常重要的

另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場景需求。


名稱欄目:redis性能分析與優(yōu)化建議-創(chuàng)新互聯(lián)
URL鏈接:http://weahome.cn/article/esodp.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部