如何破解Redis叢集難題?

如何破解Redis叢集難題?Java架構達人2019-07-10 01:17:48

如何破解Redis叢集難題?

源起

最佳化之路永無止境,在此之前一做過一些架構最佳化彙總如下:1,Redis叢集3。0。7升級到3。2。9解決讀從節點KEY過期不刪除問題,叢集有幾千萬KEY原來經核查3。0。7版本只有主上儲存過期時間,所以需要主觸發才能刪除過期的KEY,預設有主動刪除與惰性刪除同時工作,但是KEY比較多,寫的比刪除的KEY,另外讀從的話不能觸發主動刪KEY所以會有KEY沒更新問題,升級3。2。X之後解決。2,發現持久化操作時容易導致超時,後來從節點的持久化關閉,效果良好;後續計劃持久化非持久化業務分開,過期時間短的與過期時間長的分開。2,叢集擴容,升級到3。2。9版本後為了均攤QPS擴容了幾個節點,後續發現有2個節點核心版本比其他的高但是效能反而表現比其他差,後替換了同版本的核心。3,Bigkeys掃描發現有幾個hashkey元素過大超過幾千萬,單個KEY佔用記憶體幾個G後聯絡開發解決。4,建立了CacheCloud監控系統,便於分析觀察問題,另外Zabbix也使用Redis模版出現大故障時會報錯。5,後續最佳化方向轉為客戶端使用規劃的問題,主要是解決各個量大的命令平均用時超過10微秒的問題。6,每個Redis叢集版本升級在功能與效能上都有比較大的提升,需要持久化功能的集群后續可以使用4。0。2版本,另外如果使用虛擬化不建議使用XEN、Hyper-V等,最好使用vSphere壓力測試vSphere在各方面表現良好。

一,發現問題1,慢查詢 Java自學網推薦-javazx。com

slowlog get n 預設保留128個日誌執行超過10毫秒的記錄,可以根據實際情況修改

2,應用報錯

主要是應用郵件報超時

二,分析問題1,內在原因

1)API或資料結構使用不合理2)CPU飽和的問題3)持久化相關的阻塞

2,外在原因

1)CPU競爭2)記憶體交換3)網路問題

三,解決問題之內在原因1,API或資料結構使用不合理

1)發現慢查詢slowlog get n慢查詢日誌有兩個引數:slowlog-log-slower-than: 單位微妙,指定redis執行命令的最大時間,超過將記錄到慢查詢日誌中, 不接受負值,如果設定為0每條命令都要記錄到慢查詢日誌中,預設10微妙。slowlog-max-len: 設定慢查詢日誌長度,如果慢查詢日誌已經到最大值,如果有新命令需要記錄,就將最老那條記錄刪除,預設儲存128,可以線上修改,CONFIG REWRITE儲存。redis-cli127。0。0。1:6379> config get slowlog-max-len

“slowlog-max-len”

“128”127。0。0。1:6379> config set slowlog-max-len 1000OK127。0。0。1:6379> config rewriteOK

2)發現大keyredis-cli ——bigkeys

2,CPU飽和

1)統計Redis狀態500QPS左右,單個命令使用時間越少支援的QPS併發越大,比如平均1毫妙的支援1000QPS,平均100微妙的支援10000QPS。redis-cli ——stat————- data ———— ——————————- load —————————— - child -keys mem clients blocked requests connections5088981 6。51G 514 0 578132987 (+0) 3847425088997 6。51G 514 0 578133573 (+586) 3847425089018 6。51G 514 0 578134096 (+523) 3847425089005 6。51G 515 0 578134720 (+624) 3847435089048 6。51G 515 0 578135195 (+475) 3847435089093 6。51G 513 0 578135829 (+634) 3847435089117 6。51G 513 0 578136455 (+626) 3847435089081 6。51G 512 0 578136850 (+395) 3847435089121 6。51G 512 0 578137226 (+376) 384743

2)命令統計時間單位為微秒單個命令10微妙以內,儘量避免高演算法複雜的命令setex平均26del 平均43hmset平均229hmget平均12以上特別是hmset要最佳化,另外hgetall命令不建議使用

redis-cli info commandstats

Commandstats

cmdstat_get:calls=2814596805,usec=12130889716,usec_per_call=4。31cmdstat_set:calls=25674338,usec=234328226,usec_per_call=9。13cmdstat_setex:calls=910333006,usec=20767349072,usec_per_call=22。81cmdstat_del:calls=780287520,usec=33983500560,usec_per_call=43。55cmdstat_lpush:calls=1,usec=34,usec_per_call=34。00cmdstat_hset:calls=145663119,usec=499130659,usec_per_call=3。43cmdstat_hget:calls=2841141555,usec=13763160250,usec_per_call=4。84cmdstat_hmset:calls=1452658,usec=333516295,usec_per_call=229。59cmdstat_hmget:calls=970024532,usec=11909915205,usec_per_call=12。28cmdstat_hdel:calls=581004,usec=3925702,usec_per_call=6。76cmdstat_hgetall:calls=28985688,usec=555451600,usec_per_call=19。16cmdstat_hexists:calls=262547,usec=2867627,usec_per_call=10。92cmdstat_select:calls=1,usec=1,usec_per_call=1。00cmdstat_expire:calls=72409493,usec=101731304,usec_per_call=1。40cmdstat_auth:calls=1544789,usec=2890530,usec_per_call=1。87cmdstat_ping:calls=4977672,usec=2672430,usec_per_call=0。54cmdstat_echo:calls=697770,usec=380462,usec_per_call=0。55cmdstat_info:calls=32700948,usec=7243085428,usec_per_call=221。49cmdstat_config:calls=2176619,usec=31168795,usec_per_call=14。32cmdstat_subscribe:calls=1717,usec=7283,usec_per_call=4。24cmdstat_unsubscribe:calls=5506966,usec=21985846,usec_per_call=3。99cmdstat_cluster:calls=696482,usec=210160284,usec_per_call=301。75cmdstat_readonly:calls=696449,usec=437883,usec_per_call=0。63cmdstat_client:calls=697770,usec=1869891,usec_per_call=2。68cmdstat_slowlog:calls=2,usec=214,usec_per_call=107。00cmdstat_command:calls=2,usec=11824,usec_per_call=5912。00

3)持久化阻塞由於從已經關閉持久化,主要分析主的,主上只開啟了RDB且10分鐘一次,沒有開啟AOF刷盤阻塞(故不用考慮)fork阻塞:latest_fork_usec該指標不能超過1秒,這裡是275毫秒redis-cli info stats

Stats

total_connections_received:384861total_commands_processed:578276973instantaneous_ops_per_sec:509total_net_input_bytes:530863235402total_net_output_bytes:1584445816901instantaneous_input_kbps:668。38instantaneous_output_kbps:838。84rejected_connections:0sync_full:1sync_partial_ok:0sync_partial_err:0expired_keys:164683638evicted_keys:0keyspace_hits:193101765keyspace_misses:12414607pubsub_channels:0pubsub_patterns:0latest_fork_usec:275078 275毫秒migrate_cached_sockets:0

另外HugePage寫操作阻塞,這個核心已經關閉HugePages,方法如下echo never > /sys/kernel/mm/transparent_hugepage/enabled

四,解決問題之外在原因1,CPU競爭

Redis是典型的CPU密集型應用,同一臺伺服器不建議部署其他服務,如果需要不是多個Redis例項也建議繫結CPU。

2,記憶體交換

1)根據程序號cat /proc/5413/smaps |grep Swap可以檢視記憶體交換,為了避免記憶體交換,首先伺服器最好富餘1/3-1/2記憶體,fork時會生成一個程序佔用當前例項大小的記憶體,等於說記憶體加倍。

2)設定最大可用記憶體及觸發記憶體啟動lru演算法(Redis版本越高該演算法效率越高,因為Redis一直在進化)以防萬一,方法如下:127。0。0。1:6379> CONFIG GET maxmemory

“maxmemory”

“21474836480”127。0。0。1:6379> CONFIG GET maxmemory-policy

“maxmemory-policy”

“allkeys-lru”

3)可以降低系統使用swap的優先順序,由於前面對記憶體做了最佳化這裡沒有對swap調優,畢竟這些都是不得已手段,需要從架構與使用上修改效果才好。

3,網路問題

1)連線拒絕主要是網路閃斷接Redis連線數超過預設的10000,可以透過監控與修改預設值規避。目前連線不多,如果連線過多服務端的timeout可以修改一個具體的值,預設是0代表永遠不主動斷開連線。另外連線溢位,這個服務端與客戶端都需要排查,主要是看程序限制與backlog佇列是否溢位。2)網路延遲3)網絡卡軟中斷