自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

緩存用不好,Bug改到老

存儲 存儲軟件
眾所周知,緩存之所以訪問速度快,是因?yàn)榘丫彺娴慕换ソ橘|(zhì)是內(nèi)存。而常規(guī)的例如mysql數(shù)據(jù)交互介質(zhì)是磁盤。那么常見的java中或者中間件供我們可以用來做緩存的開發(fā)的工具有幾種呢?

 [[422761]]

前言

日常工作中,緩存的使用隨處可見。緩存使用得當(dāng),對提升系統(tǒng)的性能,提高用戶體驗(yàn)感有著至關(guān)重要的作用。但是如果使用不當(dāng),就會出現(xiàn)一些令人費(fèi)解或者數(shù)據(jù)混亂的問題。本文將給大家普及常見的一些緩存使用與緩存使用過程中的踩坑點(diǎn),希望能幫助大家更好的理解與使用緩存,文中如有寫的不對的地方,歡迎大家留言指正。

java緩存形式/介質(zhì)

眾所周知,緩存之所以訪問速度快,是因?yàn)榘丫彺娴慕换ソ橘|(zhì)是內(nèi)存。而常規(guī)的例如mysql數(shù)據(jù)交互介質(zhì)是磁盤。那么常見的java中或者中間件供我們可以用來做緩存的開發(fā)的工具有幾種呢?

jvm本地內(nèi)存

jvm本地內(nèi)存常見使用為定義一個全局靜態(tài)變量,保證后端服務(wù)在運(yùn)行過程中,對應(yīng)的對象空間直接保持被引用,不會被GC給回收。

guava緩存工具類

存儲數(shù)據(jù)的本質(zhì)與jvm內(nèi)存類似,內(nèi)部依靠維護(hù)java集合的子類來存儲數(shù)據(jù),但是提供了緩存數(shù)據(jù)的過期時間,過期策略等設(shè)置,像一個小型的中間件。

redis

Redis 是完全開源的,遵守 BSD 協(xié)議,是一個高性能的 key-value 數(shù)據(jù)庫。常用作數(shù)據(jù)庫、緩存和消息代理。Redis 提供了諸如字符串、散列、列表、集合、帶范圍查詢的排序集合、位圖、hyperloglogs、地理空間索引和流streams等數(shù)據(jù)結(jié)構(gòu)。Redis 內(nèi)建復(fù)制、支持 Lua 腳本、支持 LRU 緩存淘汰策略、事務(wù)和不同級別的磁盤持久化,并通過 Redis Sentinel 和 Redis Cluster 自動分區(qū)提供高可用性。同類型中間件中,Redis是最火的,沒有之一。

幾種常用緩存的對比

 

  jvm緩存 guava緩存 redis緩存
速度 第一 第二 第三
緩存數(shù)據(jù)是否占用jvm內(nèi)存
提供過期時間等策略
能否緩存大量數(shù)據(jù)
應(yīng)用重啟緩存是否丟失
使用場景 字典類型數(shù)據(jù),加載后修改頻率低 支持jvm緩存所有功能,并且適合與緩存token類型具有時效性的數(shù)據(jù) 支持guava緩存所有功能,支持日常工作所有緩存場景,應(yīng)用系統(tǒng)數(shù)據(jù)重啟與否不影響緩存數(shù)據(jù)的加載與使用

緩存常見的坑

在分析緩存的坑之前我們先來看一下緩存的增刪改查如何保證數(shù)據(jù)庫與緩存的數(shù)據(jù)一致性。

查詢

查詢時先查詢緩存,如果緩存存在直接返回,不存在則查詢數(shù)據(jù)庫,將數(shù)據(jù)庫查詢結(jié)果寫入緩存【此處默認(rèn)數(shù)據(jù)庫存在數(shù)據(jù),不存在的情況后面分析】,然后將緩存的結(jié)果數(shù)據(jù)返回。

增刪改

增刪改時先增刪改數(shù)據(jù)庫,保證數(shù)據(jù)庫數(shù)據(jù)先被修改,然后同步緩存內(nèi)數(shù)據(jù),如果中間發(fā)生異常,則調(diào)用數(shù)據(jù)庫事務(wù)回滾數(shù)據(jù)。

緩存穿透

概念

正常情況下,查詢的數(shù)據(jù)都存在,如果請求一個不存在的數(shù)據(jù),也就是緩存和數(shù)據(jù)庫都查不到這個數(shù)據(jù),每次都會去數(shù)據(jù)庫查詢,這種查詢不存在數(shù)據(jù)的現(xiàn)象我們稱為緩存穿透。如上圖,用戶一直請求接口查詢不存在的id數(shù)據(jù)【數(shù)據(jù)庫中只存在id>0的數(shù)據(jù)】,對應(yīng)的數(shù)據(jù)永遠(yuǎn)不可能在緩存中。在高并發(fā)場景下,大量請求打到了數(shù)據(jù)庫,數(shù)據(jù)庫可能被突發(fā)的流量給打掛。

3.1.2.解決方式

1.過濾垃圾數(shù)據(jù)

在知道查詢的id數(shù)據(jù)大于0或者基于id是某種規(guī)則【例如雪花id】生成的情況下。過濾掉數(shù)據(jù)庫中不可能的存在的請求。方法入口直接增加一個參數(shù)校驗(yàn)。

2.緩存空值

發(fā)生穿透的原因是數(shù)據(jù)在數(shù)據(jù)庫中不存在,那我們把null值給緩存下來,當(dāng)請求到達(dá)時直接返回null。當(dāng)然這里對緩存是必須加上過期時間的,以免后續(xù)真的存在此id的數(shù)據(jù)。過期時間不宜過長,根據(jù)實(shí)際業(yè)務(wù)場景并發(fā)量來進(jìn)行設(shè)置。

3.IP攔截

對于惡意的攻擊請求,一直請求無效的數(shù)據(jù),可以設(shè)置ip請求策略。如果對應(yīng)的ip短時間內(nèi)發(fā)起了大量請求,且請求參數(shù)均為不存在的數(shù)據(jù)。則將ip進(jìn)行封禁一段時間,不允許再次請求系統(tǒng)。

**4.布隆過濾器

布隆過濾器(BloomFilter)用來判斷某個元素(key)是否存在于某個集合中我們把有數(shù)據(jù)的key都放到BloomFilter中,每次查詢的時候都先去BloomFilter判斷,如果沒有就直接返回null 。

注意BloomFilter沒有刪除操作,對于刪除的key,查詢就會經(jīng)過BloomFilter然后查詢緩存再查詢數(shù)據(jù)庫,所以BloomFilter可以結(jié)合緩存空值用,對于刪除的key,可以在緩存中緩存null

緩存擊穿

嚴(yán)格意義上說緩存穿透是緩存擊穿的一種。只不過緩存擊穿是查詢的有效數(shù)據(jù)。在高并發(fā)情況下,查詢緩存時,緩存中的數(shù)據(jù)不存在或者已經(jīng)失效了。那么會導(dǎo)致大量的請求打到了數(shù)據(jù)庫,打掛數(shù)據(jù)庫

解決方式

先來分析一下場景,大量請求同時到了緩存,緩存不存在,再請求數(shù)據(jù)庫。然后再將請求結(jié)果寫入到緩存。問題就是多個線程幾乎同時讀取緩存,又幾乎同時重寫緩存。多線程并發(fā)下解決問題,當(dāng)然是用鎖。單體應(yīng)用可以使用synchronized關(guān)鍵字或者ReentrantLock進(jìn)行加鎖,分布式服務(wù)則可使用分布式鎖的方式來實(shí)現(xiàn)加鎖。

大致的偽代碼如下:

  1. public Object query(){ 
  2.     //查詢緩存,存在則直接返回 
  3.     Object value = queryCache; 
  4.     //這里為了防止緩存穿透,可以緩存下空對象,而不是null,保證null值是必須查詢緩存的 
  5.     if(Objects.nonNull(value)){ 
  6.         return value; 
  7.     } 
  8.     //加鎖訪問數(shù)據(jù)庫 
  9.     lock{ 
  10.         //二次查詢緩存,避免在高并發(fā)的情況下,多個線程都到了爭搶鎖的這個環(huán)節(jié),在此之前 
  11.         //已經(jīng)有線程拿到鎖寫入緩存了,無需再次查詢數(shù)據(jù)庫,直接返回即可 
  12.         value = queryCache; 
  13.         if(Objects.nonNull(value)){ 
  14.             return value; 
  15.         } 
  16.         //查詢數(shù)據(jù)庫 
  17.         value = queryDb; 
  18.         //設(shè)置緩存數(shù)據(jù) 
  19.         setCache; 
  20.         //返回結(jié)果 
  21.         return value; 
  22.     } 
  23. 復(fù)制代碼 

緩存雪崩

概念

緩存雪崩也是緩存擊穿的一種,緩存設(shè)置了過期時間/淘汰策略的情況下,在某個時間點(diǎn),大量的緩存失效。高并發(fā)情況下大量請求打到了數(shù)據(jù)庫。

解決方式

緩存雪崩時,請求方式與緩存擊穿一致,主要如何防護(hù)緩存雪崩,基本指導(dǎo)思想為:

熱點(diǎn)數(shù)據(jù)設(shè)置永不過期,緩存淘汰策略為淘汰最早過期數(shù)據(jù)

數(shù)據(jù)緩存過期時間設(shè)置高離散度隨機(jī)值,避免某個時間點(diǎn),大量緩存同時過期。

性能問題

概念

使用了緩存,但是性能還是上不去的場景。例如雙十一場景下,訂單數(shù)據(jù)量比較大。如果新增修改刪除所有操作都要先操作一遍數(shù)據(jù)庫,再回寫緩存的話效率是很低的。

解決方式

把緩存當(dāng)做數(shù)據(jù)庫來使用,當(dāng)然這里需要使用redis這種高可用的持久化緩存中間件。數(shù)據(jù)存在redis中,數(shù)據(jù)交互都直接交互redis??高^流量高峰之后,啟用定時任務(wù),將redis的數(shù)據(jù)刷入至數(shù)據(jù)庫或者ES。當(dāng)然這里也可以使用消息隊(duì)列,這里不具體展開。

總結(jié)

本文著重講述了緩存的增刪改查策略與日??狱c(diǎn)。

數(shù)據(jù)一致性

查詢操作,先走緩存再走數(shù)據(jù)庫,再更新緩存。

增刪改操作,先走數(shù)據(jù)庫再更新緩存。

坑點(diǎn)

從緩存雪崩去理解緩存穿透與緩存擊穿。

高性能

讀寫持久化緩存數(shù)據(jù),異步刷盤mysql。

本文轉(zhuǎn)載自微信公眾號「碼農(nóng)小胖哥」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請聯(lián)系碼農(nóng)小胖哥公眾號。

 

責(zé)任編輯:武曉燕 來源: 碼農(nóng)小胖哥
相關(guān)推薦

2020-03-08 16:58:51

Chrome瀏覽器代碼

2020-10-22 07:09:19

TCP網(wǎng)絡(luò)協(xié)議

2018-06-28 09:40:20

Redis誤區(qū)集群模式

2019-11-27 10:07:55

程序員工程師JavaScript

2021-05-20 10:02:50

系統(tǒng)Redis技巧

2021-09-11 19:00:54

Intro元素MemoryCache

2020-10-22 10:20:58

互聯(lián)網(wǎng)程序技術(shù)

2020-10-23 09:45:06

程序員能力開發(fā)

2011-06-14 16:31:27

QT

2011-08-17 15:23:37

iPhone開發(fā)Objective-CCocoa Touch

2019-10-10 15:40:17

redisbug數(shù)據(jù)庫

2014-07-23 10:02:56

老式電腦ENIAC

2018-08-31 07:33:58

2019-09-26 10:58:31

電腦省錢重啟

2009-04-13 10:38:49

ITIL運(yùn)維管理摩卡

2016-10-20 14:04:09

2013-10-31 11:12:56

IECSS

2013-10-30 09:57:43

IECSS

2014-05-22 16:32:48

bug查找bug

2014-11-14 14:03:17

微軟安全漏洞bug
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號