關於redis堆外內存溢出,以及(穿透、雪崩、擊穿)問題


lettuce堆外內存溢出bug

 

當進行壓力測試時后期后出現堆外內存溢出OutOfDirectMemoryError

 

產生原因:

 

1)、springboot2.0以后默認使用lettuce作為操作redis的客戶端,它使用netty進行網絡通信

 

2)、lettuce的bug導致netty堆外內存溢出。netty如果沒有指定堆外內存,默認使用Xms的值,可以使用-Dio.netty.maxDirectMemory進行設置

 

解決方案:

 

由於是lettuce的bug造成,不要直接使用-Dio.netty.maxDirectMemory去調大虛擬機堆外內存,治標不治本。

 

1)、升級lettuce客戶端。但是沒有解決的

 

2)、切換使用jedis

 

lettuce和jedis是操作redis的底層客戶端,RedisTemplate是再次封裝

 1  
 2  
 3 <dependency>
 4   <groupId>org.springframework.boot</groupId>
 5   <artifactId>spring-boot-starter-data-redis</artifactId>
 6   <exclusions>
 7     <exclusion>
 8       <groupId>io.lettuce</groupId>
 9       <artifactId>lettuce-core</artifactId>
10     </exclusion>
11   </exclusions>
12 </dependency>
13 <dependency>
14     <groupId>redis.clients</groupId>
15     <artifactId>jedis</artifactId>
16 </dependency>

 

緩存:穿透、雪崩、擊穿

 

穿透

 

緩存穿透是指緩存和數據庫中都沒有的數據,而用戶不斷發起請求,如發起為id為“-1”的數據或id為特別大不存在的數據。這時的用戶很可能是攻擊者,攻擊會導致數據庫壓力過大。

 

解決方案

 

緩存空對象,MVC攔截器

 

雪崩

 

緩存雪崩是指在我們設置緩存時key采用了相同的過期時間,導致緩存在某一時刻同時失效,請求全部轉發到DB,DB瞬時壓力過重雪崩。

 

解決方案

 

規避雪崩:緩存數據的過期時間設置隨機,防止同一時間大量數據過期現象發生。

 

如果緩存數據庫是分布式部署,將熱點數據均勻分布在不同緩存數據庫中。

 

設置熱點數據永遠不過期。

 

出現雪崩:降級 熔斷

 

事前:盡量保證整個 redis 集群的高可用性,發現機器宕機盡快補上。選擇合適的內存淘汰策略。

 

事中:本地ehcache緩存 + hystrix限流&降級,避免MySQL崩掉

 

事后:利用 redis 持久化機制保存的數據盡快恢復緩存

 

擊穿

 

緩存擊穿 指 並發查同一條數據。緩存擊穿是指緩存中沒有但數據庫中有的數據(一般是緩存時間到期),這時由於並發用戶特別多,同時讀緩存沒讀到數據,又同時去數據庫去取數據,引起數據庫壓力瞬間增大,造成過大壓力

 

緩存雪崩是不同數據都過期了,很多數據都查不到從而查數據庫。

 

解決方案

 

設置熱點數據永遠不過期。

 

加互斥鎖:業界比較常用的做法,是使用mutex。簡單地來說,就是在緩存失效的時候(判斷拿出來的值為空),不是立即去load db去數據庫加載,而是先使用緩存工具的某些帶成功操作返回值的操作(比如Redis的SETNX或者Memcache的ADD)去set一個mutex key,當操作返回成功時,再進行load db的操作並回設緩存;否則,就重試整個get緩存的方法。

 

擴展

 

如果是單機服務可以使用 synchronized(this), JUC(look)

 

鎖時序問題

 

之前的邏輯是查緩存沒有,然后取競爭鎖查數據庫,這樣就造成多次查數據庫。

 

解決方法:

 

競爭到鎖后,再次確認緩存中沒有,再去查數據庫。

 

鎖競爭模擬,多個服務同事操作同一個命令

 
 
 
 
 
 
 

復制微服務

 
 
 
 
 
 
 

分布式緩存

 

本地緩存問題:每個微服務都要有緩存服務、數據更新時只更新自己的緩存,造成緩存數據不一致

 

解決方案:分布式緩存,微服務共用 緩存中間件

 

分布式項目時,但本地鎖只能鎖住當前服務,需要分布式鎖

 

redis分布式鎖的原理:setnx,同一時刻只能設置成功一個

 
 
set 命令 -- Redis中國用戶組(CRUG)

redis

 

設置好了鎖,玩意服務出現宕機,沒有執行刪除鎖邏輯,這就造成了死鎖

 

解決:設置過期時間

 

業務還沒執行完鎖就過期了,別人拿到鎖,自己執行完去刪了別人的鎖

 

解決:鎖續期(redisson有看門狗),。刪鎖的時候明確是自己的鎖。如uuid

 

判斷uuid對了,但是將要刪除的時候鎖過期了,別人設置了新值,那刪除了別人的鎖

 

解決:刪除鎖必須保證原子性(保證判斷和刪鎖是原子的)。使用redis+Lua腳本完成,腳本是原子的


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM