java面試準備之數據庫(Mysql+Redis)

MYSQL

一、事務

事務:事務是由一組SQL語句組成的邏輯處理單元,事務具有4屬性,通常稱爲事務的ACID屬性,一個最小的不可再分的工作單元;通常一個事務對應一個完整的業務(例如銀行賬戶轉賬業務,該業務就是一個最小的工作單元)

(一)事務四大特性

通過數據庫的redo log重做日誌,來保證事務的持久性與原子性。
通過數據庫的undo log撤銷日誌,來保證事務的一致性
通過鎖機制+MVCC來保證事務隔離性
1.原子性(Actomicity):事務是一個原子操作單元,其對數據的修改,要麼全都執行,要麼全都不執行。(一個事務爲一個原子,不可分割,要麼成功,要麼失敗)
2.一致性(Consistent):在事務開始和完成時,數據都必須保持一致狀態。這意味着所有相關的數據規則都必須應用於事務的修改,以操持完整性;事務結束時,所有的內部數據結構(如B樹索引或雙向鏈表)也都必須是正確的。(經過一系列改動及異常崩潰,最後的結果是我要的)
強一致性:讀操作可以立即讀到提交的更新操作。
弱一致性:提交的更新操作,不一定立即會被讀操作讀到,此種情況會存在一個不一致窗口,指的是讀操作可以讀到最新值的一 段時間。
最終一致性:是弱一致性的特例。事務更新一份數據,最終一致性保證在沒有其他事務更新同樣的值的話,最終所有的事務都會 讀到之前事務更新的最新值。如果沒有錯誤發生,不一致窗口的大小依賴於:通信延遲,系統負載等。其他一致性變體還有:
單調一致性:如果一個進程已經讀到一個值,那麼後續不會讀到更早的值。
會話一致性:保證客戶端和服務器交互的會話過程中,讀操作可以讀到更新操作後的最新值。
3.隔離性(Isolation):數據庫系統提供一定的隔離機制,保證事務在不受外部併發操作影響的“獨立”環境執行。這意味着事務處理過程中的中間狀態對外部是不可見的,反之亦然。(mvcc,隔離級別)
4.持久性(Durable):事務完成之後,它對於數據的修改是永久性的,即使出現系統故障也能夠保持。(一旦提交成功,那麼事務涉及的數據都會持久化,即使系統崩潰,修改的數據也不會丟失)

(二)事務隔離級別

1.未提交讀
讀未提交:一個事務可以讀取到另一個事務未提交的修改。這會帶來髒讀、幻讀、不可重複讀問題。(基本沒用)
總結:該級別防止了一個事務修改數據的同時另一個事務修改(對同一數據,下同),沒防止修改的同時讀(即僅對修改加了共享鎖)。
2.提交讀
讀已提交:一個事務只能讀取另一個事務已經提交的修改。其避免了髒讀,但仍然存在不可重複讀和幻讀問題。
總結:該級別防止了一個事務修改的同時另一個事務修改,也防止修改的同時讀,但沒防止讀的時候修改(即僅對修改加了排它鎖)。
3.可重複讀(MVCC解決該問題–多版本併發控制機制)
可重複讀:同一個事務中多次讀取相同的數據返回的結果是一樣的。其避免了髒讀和不可重複讀問題,但幻讀依然存在。
總結:該級別防止了一個事務修改的同時另一個事務修改,也防止修改的同時讀,也防止讀的時候修改,但沒防止讀的時候新增/刪除(對影響的數據行的修改、讀加了排它鎖,沒對錶進行加鎖,解決幻讀,不一定要對錶加鎖,即隔離級別變爲4,也可以通過MVCC解決)。
4.可串行化(在每個讀的數據行上加共享鎖)
事務串行執行。避免了以上所有問題(沒有併發)。
兩段式鎖:定義了兩種鎖,讀鎖和寫鎖,只有讀-讀可以共享,其餘的都阻塞。兩段式鎖指的是加鎖和解鎖不能交替,也就是在一個事務內,解鎖操作之後不能再有任何的加鎖操作,如果嚴格按照這個協議來操作數據,那麼最終的執行一定是可串行化。
總結:表加鎖。
MySQL數據庫(InnoDB引擎)默認使用可重複讀( Repeatable read)

二、索引

(一)概念

索引用於快速找出在某個列中有一特定值的行,不使用索引,MySQL必須從第一條記錄開始讀完整個表,直到找出相關的行,表越大,查詢數據所花費的時間就越多,如果表中查詢的列有一個索引,MySQL能夠快速到達一個位置去搜索數據文件,而不必查看所有數據,那麼將會節省很大一部分時間。
假如一張表有一億條數據 ,需要查找其中某一條數據,按照常規邏輯,一條一條的去匹配的話,最壞的情況下需要匹配一億次才能得到結果,用大O標記法就是O(n)最壞時間複雜度,這是無法接受的,而且這一億條數據顯然不能一次性讀入內存供程序使用,因此,這一億次匹配在不經緩存優化的情況下就是一億次IO開銷,以現在磁盤的IO能力和CPU的運算能力,有可能需要幾個月才能得出結果。如果把這張錶轉換成平衡樹結構(一棵非常茂盛和節點非常多的樹),假設這棵樹有10層,那麼只需要10次IO開銷就能查找到所需要的數據,速度以指數級別提升,用大O標記法就是O(log n),n是記錄總樹,底數是樹的分叉數,結果就是樹的層次數。

(二)索引優缺點

優點:
1、所有的MySql列類型(字段類型)都可以被索引,也就是可以給任意字段設置索引
2、大大加快數據的查詢速度
缺點:
 1、創建索引和維護索引要耗費時間,並且隨着數據量的增加所耗費的時間也會增加
 2、索引也需要佔空間,我們知道數據表中的數據也會有最大上線設置的,如果我們有大量的索引,索引文件可能會比數據文件更快達到上線值
 3、當對錶中的數據進行增加、刪除、修改時,索引也需要動態的維護,降低了數據的維護速度。

(三)MyISAM(非聚集索引)和InnoDB(聚集索引)

MyISAM引擎使用B+Tree作爲索引結構,葉節點的data域存放的是數據記錄的地址,即:MyISAM索引文件和數據文件是分離的,MyISAM的索引文件僅僅保存數據記錄的地址。MyISAM中索引檢索的算法爲首先按照B+Tree搜索算法搜索索引,如果指定的Key存在,則取出其data域的值,然後以data域的值爲地址,讀取相應數據記錄。MyISAM的索引方式也叫做“非聚集”的。
InnoDB引擎也使用B+Tree作爲索引結構,但是InnoDB的數據文件本身就是索引文件,葉節點data域保存了完整的數據記錄。這個索引的key是數據表的主鍵,因此InnoDB表數據文件本身就是主索引。這種索引叫做“聚焦索引”。InnoDB的輔助索引的data域存儲相應記錄主鍵的值而不是地址。換句話說,InnoDB的所有輔助索引都引用主鍵作爲data域。聚集索引這種實現方式使得按主鍵的搜索十分高效,但是輔助索引搜索需要檢索兩遍索引:首先檢索輔助索引獲得主鍵,然後用主鍵到主索引中檢索獲得記錄。InnoDB的索引實現後,不建議使用過長的字段作爲主鍵,因爲所有輔助索引都引用主索引,過長的主索引會令輔助索引變得過大。在Innodb中也不建議使用非單調的字段作爲主鍵,因爲InnoDB數據文件本身是一顆B+Tree,非單調的主鍵會造成在插入新記錄時數據文件爲了維持B+Tree的特性而頻繁的分裂調整,十分低效,建議使用自增字段作爲主鍵。

(四)存儲引擎InnoDB和MyISAM的區別

1.InnoDB支持事務,MyISAM不支持。
2.MyISAM適合查詢以及插入爲主的應用,InnoDB適合頻繁修改以及涉及到安全性較高的應用。
3.InnoDB支持外鍵,MyISAM不支持。
4.從MySQL5.5.5以後,InnoDB是默認引擎。
5.MyISAM支持全文類型索引,而InnoDB不支持全文索引。
6.InnoDB中不保存表的總行數,select count() from table時,InnoDB需要掃描整個表計算有多少行,但MyISAM只需簡單讀出保存好的總行數即可。注:當count()語句包含where條件時MyISAM也需掃描整個表。
7.對於自增長的字段,InnoDB中必須包含只有該字段的索引,但是在MyISAM表中可以和其他字段一起建立聯合索引。
8.清空整個表時,InnoDB是一行一行的刪除,效率非常慢。MyISAM則會重建表。MyisAM使用delete語句刪除後並不會立刻清理磁盤空間,需要定時清理,命令:OPTIMIZE table dept;
9.InnoDB支持行鎖(某些情況下還是鎖整表,如 update table set a=1 where user like ‘%lee%’)
10.Myisam創建表生成三個文件:.frm 數據表結構 、 .myd 數據文件 、 .myi 索引文件,Innodb只生成一個 .frm文件,數據存放在ibdata1.log
11.現在一般都選用InnoDB,主要是MyISAM的全表鎖,讀寫串行問題,併發效率鎖表,效率低,MyISAM對於讀寫密集型應用一般是不會去選用的。
12.應用場景:
MyISAM不支持事務處理等高級功能,但它提供高速存儲和檢索,以及全文搜索能力。如果應用中需要執行大量的SELECT查詢,那麼MyISAM是更好的選擇。
InnoDB用於需要事務處理的應用程序,包括ACID事務支持。如果應用中需要執行大量的INSERT或UPDATE操作,則應該使用InnoDB,這樣可以提高多用戶併發操作的性能。
下面的表總結了何時使用聚集索引或非聚集索引(很重要)。
動作描述 使用聚集索引 使用非聚集索引
列經常被分組排序 應 應
返回某範圍內的數據 應 不應
一個或極少不同值 不應 不應
小數目的不同值 應 不應
大數目的不同值 不應 應
頻繁更新的列 不應 應
外鍵列 應 應
主鍵列 應 應
頻繁修改索引列 不應 應

(五)B+樹相交於B樹的優點以及缺點

優點:
1.層級更低,IO 次數更少
2.每次都需要查詢到葉子節點,查詢性能穩定
3.葉子節點形成有序鏈表,範圍查詢方便
缺點:B+樹最大的性能問題是會產生大量的隨機IO,隨着新數據的插入,葉子節點會慢慢分裂,邏輯上連續的葉子節點在物理上往往不連續,甚至分離的很遠,但做範圍查詢時,會產生大量讀隨機IO。對於大量的隨機寫也一樣,舉一個插入key跨度很大的例子,如7->1000->3->2000 … 新插入的數據存儲在磁盤上相隔很遠,會產生大量的隨機寫IO.

(六)索引的使用

何時使用索引
MySQL每次查詢只使用一個索引。與其說是“數據庫查詢只能用到一個索引”,倒不如說,和全表掃描比起來,去分析兩個索引B+樹更加耗費時間。所以where A=a and B=b這種查詢使用(A,B)的組合索引最佳,B+樹根據(A,B)來排序。
(1)主鍵,unique字段;
(2)和其他表做連接的字段需要加索引;
(3)在where裏使用>,≥,=,<,≤,is null和between等字段;
(4)使用不以通配符開始的like,where A like ‘China%’;
(5)聚集函數MIN(),MAX()中的字段;
(6)order by和group by字段;
何時不使用索引
(1)表記錄太少;
(2)數據重複且分佈平均的字段(只有很少數據值的列);
(3)經常插入、刪除、修改的表要減少索引;
(4)text,image等類型不應該建立索引,這些列的數據量大(假如text前10個字符唯一,也可以對text前10個字符建立索引);
(5)MySQL能估計出全表掃描比使用索引更快時,不使用索引;
索引何時失效
(1)組合索引未使用最左前綴,例如組合索引(A,B),where B=b不會使用索引;
(2)like未使用最左前綴,where A like ‘%China’;
(3)搜索一個索引而在另一個索引上做order by,where A=a order by B,只使用A上的索引,因爲查詢只使用一個索引 ;
(4)or會使索引失效。如果查詢字段相同,也可以使用索引。例如where A=a1 or A=a2(生效),where A=a or B=b(失效)
(5)如果列類型是字符串,要使用引號。例如where A=‘China’,否則索引失效(會進行類型轉換);
(6)在索引列上的操作,函數(upper()等)、or、!=(<>)、not in,在 where 子句中對字段進行 null 值判斷,使用!=或<>操作符等;

三、數據庫三範式

第一範式:1NF是對屬性的原子性約束,要求屬性具有原子性,不可再分解;
第二範式:2NF是對記錄的惟一性約束,要求記錄有惟一標識,即實體的惟一性;
第三範式:3NF是對字段冗餘性的約束,即任何字段不能由其他字段派生出來,它要求字段沒有冗餘。。
範式化設計優缺點:
優點:
可以儘量得減少數據冗餘,使得更新快,體積小
缺點:對於查詢需要多個表進行關聯,減少寫得效率增加讀得效率,更難進行索引優化
反範式化:
優點:可以減少表得關聯,可以更好得進行索引優化
缺點:數據冗餘以及數據異常,數據得修改需要更多的成本

四、SQL語句的優化

查詢的優化
1、保證在實現功能的基礎上,儘量減少對數據庫的訪問次數;
2、通過搜索參數,儘量減少對錶的訪問行數,最小化結果集,從而減輕網絡負擔;
3、能夠分開的操作儘量分開處理,提高每次的響應速度;
4、在數據窗口使用SQL時,儘量把使用的索引放在選擇的首列;
5、算法的結構儘量簡單;
6、在查詢時,不要過多地使用通配符如:SELECT * FROM T1 語句,要用到幾列就選擇幾列,如:SELECT COL1,COL2 FROM T1;
7、在可能的情況下儘量限制儘量結果集行數如:SELECT TOP 300 COL1,COL2,COL3 FROM T1,因爲某些情況下用戶是不需要那麼多的數據的。
Mysql中的鎖類型
MyISAM支持表鎖,InnoDB支持表鎖和行鎖,默認爲行鎖
表級鎖:開銷小,加鎖快,不會出現死鎖。鎖定粒度大,發生鎖衝突的概率最高,併發量最低
行級鎖:開銷大,加鎖慢,會出現死鎖。鎖力度小,發生鎖衝突的概率小,併發度最高

Redis

一、Redis簡介

簡單來說 redis 就是一個數據庫(nosql),不過與傳統數據庫不同的是 redis 的數據是存在內存中的,所以讀寫速度非常快,因此 redis 被廣泛應用於緩存方向。另外,redis 也經常用來做分佈式鎖。redis 提供了多種數據類型來支持不同的業務場景。除此之外,redis 支持事務 、持久化、LUA腳本、LRU驅動事件、多種集羣方案。

(一)爲什麼要用redis來做緩存

可以從高性能、高併發兩個方面來說
高性能:
假如用戶第一次訪問數據庫中的某些數據。這個過程會比較慢,因爲是從硬盤上讀取的。將該用戶訪問的數據存在緩存中,這樣下一次再訪問這些數據的時候就可以直接從緩存中獲取了。操作緩存就是直接操作內存,所以速度相當快。如果數據庫中的對應數據改變的之後,同步改變緩存中相應的數據即可!
高併發:
直接操作緩存能夠承受的請求是遠遠大於直接訪問數據庫的,所以我們可以考慮把數據庫中的部分數據轉移到緩存中去,這樣用戶的一部分請求會直接到緩存這裏而不用經過數據庫。

(二)爲什麼要用 redis 而不用 map/guava 做緩存?

緩存分爲本地緩存和分佈式緩存。以 Java 爲例,使用自帶的 map 或者 guava 實現的是本地緩存,最主要的特點是輕量以及快速,生命週期隨着 jvm 的銷燬而結束,並且在多實例的情況下,每個實例都需要各自保存一份緩存,緩存不具有一致性。
使用 redis 或 memcached 之類的稱爲分佈式緩存,在多實例的情況下,各實例共用一份緩存數據,緩存具有一致性。缺點是需要保持 redis 或 memcached服務的高可用,整個程序架構上較爲複雜。

二、redis和memcached的區別

(一)對於 redis 和 memcached 的區別。

現在公司一般都是用 redis 來實現緩存,而且 redis 自身也越來越強大了!
1.redis支持更豐富的數據類型(支持更復雜的應用場景):Redis不僅僅支持簡單的k/v類型的數據,同時還提供list,set,zset,hash等數據結構的存儲。memcache支持簡單的數據類型,String。
2.Redis支持數據的持久化,可以將內存中的數據保持在磁盤中,重啓的時候可以再次加載進行使用,而Memecache把數據全部存在內存之中。
3.集羣模式:memcached沒有原生的集羣模式,需要依靠客戶端來實現往集羣中分片寫入數據;但是 redis 目前是原生支持 cluster 模式的.
4.Memcached是多線程,非阻塞IO複用的網絡模型;Redis使用單線程的多路 IO 複用模型。

(二)redis的線程模型

redis 內部使用文件事件處理器 file event handler,這個文件事件處理器是單線程的,所以 redis 才叫做單線程的模型。它採用 IO 多路複用機制同時監聽多個 socket,根據 socket 上的事件來選擇對應的事件處理器進行處理。
文件事件處理器的結構包含 4 個部分:
1.多個 socket
2.IO 多路複用程序
3.文件事件分派器
4.事件處理器(連接應答處理器、命令請求處理器、命令回覆處理器)
多個 socket 可能會併發產生不同的操作,每個操作對應不同的文件事件,但是 IO 多路複用程序會監聽多個 socket,會將 socket 產生的事件放入隊列中排隊,事件分派器每次從隊列中取出一個事件,把該事件交給對應的事件處理器進行處理。

三、redis常見數據結構及使用場景分析

1.String
常用命令: set,get,decr,incr,mget 等。
String數據結構是簡單的key-value類型,value其實不僅可以是String,也可以是數字。
常規key-value緩存應用;常規計數:微博數,粉絲數等。
2.Hash
常用命令: hget,hset,hgetall 等。
hash 是一個 string 類型的 field 和 value 的映射表,hash 特別適合用於存儲對象,後續操作的時候,你可以直接僅僅修改這個對象中的某個字段的值。 比如我們可以 hash 數據結構來存儲用戶信息,商品信息等等。
3.List
常用命令: lpush,rpush,lpop,rpop,lrange等
list 就是鏈表,Redis list 的應用場景非常多,也是Redis最重要的數據結構之一,比如微博的關注列表,粉絲列表,消息列表等功能都可以用Redis的 list 結構來實現。
Redis list 的實現爲一個雙向鏈表,即可以支持反向查找和遍歷,更方便操作,不過帶來了部分額外的內存開銷。
另外可以通過 lrange 命令,就是從某個元素開始讀取多少個元素,可以基於 list 實現分頁查詢,這個很棒的一個功能,基於 redis 實現簡單的高性能分頁,可以做類似微博那種下拉不斷分頁的東西(一頁一頁的往下走),性能高。
4.Set
常用命令:
sadd,spop,smembers,sunion 等
set 對外提供的功能與list類似是一個列表的功能,特殊之處在於 set 是可以自動排重的。
當你需要存儲一個列表數據,又不希望出現重複數據時,set是一個很好的選擇,並且set提供了判斷某個成員是否在一個set集合內的重要接口,這個也是list所不能提供的。可以基於 set 輕易實現交集、並集、差集的操作。
比如:在微博應用中,可以將一個用戶所有的關注人存在一個集合中,將其所有粉絲存在一個集合。Redis可以非常方便的實現如共同關注、共同粉絲、共同喜好等功能。這個過程也就是求交集的過程,具體命令如下:
sinterstore key1 key2 key3 將交集存在key1內
5.Sorted Set
常用命令: zadd,zrange,zrem,zcard等
和set相比,sorted set增加了一個權重參數score,使得集合中的元素能夠按score進行有序排列。
舉例: 在直播系統中,實時排行信息包含直播間在線用戶列表,各種禮物排行榜,彈幕消息(可以理解爲按消息維度的消息排行榜)等信息,適合使用 Redis 中的 Sorted Set 結構進行存儲。

四、redis設置過期時間及內存淘汰機制

(一)redis 設置過期時間

Redis中有個設置時間過期的功能,即對存儲在 redis 數據庫中的值可以設置一個過期時間。作爲一個緩存數據庫,這是非常實用的。如我們一般項目中的 token 或者一些登錄信息,尤其是短信驗證碼都是有時間限制的,按照傳統的數據庫處理方式,一般都是自己判斷過期,這樣無疑會嚴重影響項目性能。
我們 set key 的時候,都可以給一個 expire time,就是過期時間,通過過期時間我們可以指定這個 key 可以存活的時間。
如果假設你設置了一批 key 只能存活1個小時,那麼接下來1小時後,redis是怎麼對這批key進行刪除的?
定期刪除+惰性刪除。
通過名字大概就能猜出這兩個刪除方式的意思了。
定期刪除:redis默認是每隔 100ms 就隨機抽取一些設置了過期時間的key,檢查其是否過期,如果過期就刪除。注意這裏是隨機抽取的。爲什麼要隨機呢?你想一想假如 redis 存了幾十萬個 key ,每隔100ms就遍歷所有的設置過期時間的 key 的話,就會給 CPU 帶來很大的負載!
惰性刪除:定期刪除可能會導致很多過期 key 到了時間並沒有被刪除掉。所以就有了惰性刪除。假如你的過期 key,靠定期刪除沒有被刪除掉,還停留在內存裏,除非你的系統去查一下那個 key,纔會被redis給刪除掉。這就是所謂的惰性刪除,也是夠懶的哈!
但是僅僅通過設置過期時間還是有問題的。我們想一下:如果定期刪除漏掉了很多過期 key,然後你也沒及時去查,也就沒走惰性刪除,此時會怎麼樣?如果大量過期key堆積在內存裏,導致redis內存塊耗盡了。怎麼解決這個問題呢? redis 內存淘汰機制。

(二)redis 內存淘汰機制(MySQL裏有2000w數據,Redis中只存20w的數據,如何保證Redis中的數據都是熱點數據)

配置網址: http://download.redis.io/redis-stable/redis.conf
redis 提供 6種數據淘汰策略:
volatile-lru:從已設置過期時間的數據集(server.db[i].expires)中挑選最近最少使用的數據淘汰
volatile-ttl:從已設置過期時間的數據集(server.db[i].expires)中挑選將要過期的數據淘汰
volatile-random:從已設置過期時間的數據集(server.db[i].expires)中任意選擇數據淘汰
allkeys-lru:當內存不足以容納新寫入數據時,在鍵空間中,移除最近最少使用的key(這個是最常用的)
allkeys-random:從數據集(server.db[i].dict)中任意選擇數據淘汰
no-eviction:禁止驅逐數據,也就是說當內存不足以容納新寫入數據時,新寫入操作會報錯。這個應該沒人使用吧

五、redis持久化機制

Redis不同於Memcached的很重一點就是,Redis支持持久化,而且支持兩種不同的持久化操作。Redis的一種持久化方式叫快照(snapshotting,RDB),另一種方式是隻追加文件(append-only file,AOF)。這兩種方法各有千秋,下面我會詳細這兩種持久化方法是什麼,怎麼用,如何選擇適合自己的持久化方法。

(一)快照(snapshotting)持久化(RDB)

Redis可以通過創建快照來獲得存儲在內存裏面的數據在某個時間點上的副本。Redis創建快照之後,可以對快照進行備份,可以將快照複製到其他服務器從而創建具有相同數據的服務器副本(Redis主從結構,主要用來提高Redis性能),還可以將快照留在原地以便重啓服務器的時候使用。
快照持久化是Redis默認採用的持久化方式,在redis.conf配置文件中默認有此下配置:

(二)AOF(append-only file)持久化

與快照持久化相比,AOF持久化 的實時性更好,因此已成爲主流的持久化方案。默認情況下Redis沒有開啓AOF(append only file)方式的持久化,可以通過appendonly參數開啓:appendonly yes
開啓AOF持久化後每執行一條會更改Redis中的數據的命令,Redis就會將該命令寫入硬盤中的AOF文件。AOF文件的保存位置和RDB文件的位置相同,都是通過dir參數設置的,默認的文件名是appendonly.aof。
在Redis的配置文件中存在三種不同的 AOF 持久化方式,它們分別是:
appendfsync always #每次有數據修改發生時都會寫入AOF文件,這樣會嚴重降低Redis的速度
appendfsync everysec #每秒鐘同步一次,顯示地將多個寫命令同步到硬盤
appendfsync no #讓操作系統決定何時進行同步
爲了兼顧數據和寫入性能,用戶可以考慮 appendfsync everysec選項 ,讓Redis每秒同步一次AOF文件,Redis性能幾乎沒受到任何影響。而且這樣即使出現系統崩潰,用戶最多隻會丟失一秒之內產生的數據。當硬盤忙於執行寫入操作的時候,Redis還會優雅的放慢自己的速度以便適應硬盤的最大寫入速度。

六、緩存雪崩和緩存穿透問題解決方案

(一)緩存雪崩

簡介:緩存同一時間大面積的失效,所以,後面的請求都會落到數據庫上,造成數據庫短時間內承受大量請求而崩掉。
解決辦法(中華石杉老師在他的視頻中提到過,視頻地址在最後一個問題中有提到):
事前:儘量保證整個 redis 集羣的高可用性,發現機器宕機儘快補上。選擇合適的內存淘汰策略。
事中:本地ehcache緩存 + hystrix限流&降級,避免MySQL崩掉
事後:利用 redis 持久化機制保存的數據儘快恢復緩存

(二)緩存穿透

簡介:一般是黑客故意去請求緩存中不存在的數據,導致所有的請求都落到數據庫上,造成數據庫短時間內承受大量請求而崩掉。
解決辦法: 有很多種方法可以有效地解決緩存穿透問題,最常見的則是採用布隆過濾器,將所有可能存在的數據哈希到一個足夠大的bitmap中,一個一定不存在的數據會被 這個bitmap攔截掉,從而避免了對底層存儲系統的查詢壓力。另外也有一個更爲簡單粗暴的方法(我們採用的就是這種),如果一個查詢返回的數據爲空(不管是數 據不存在,還是系統故障),我們仍然把這個空結果進行緩存,但它的過期時間會很短,最長不超過五分鐘。

八、如何保證緩存與數據庫雙寫時的數據一致性?

你只要用緩存,就可能會涉及到緩存與數據庫雙存儲雙寫,你只要是雙寫,就一定會有數據一致性的問題,那麼你如何解決一致性問題?
一般來說,就是如果你的系統不是嚴格要求緩存+數據庫必須一致性的話,緩存可以稍微的跟數據庫偶爾有不一致的情況,最好不要做這個方案,讀請求和寫請求串行化,串到一個內存隊列裏去,這樣就可以保證一定不會出現不一致的情況
串行化之後,就會導致系統的吞吐量會大幅度的降低,用比正常情況下多幾倍的機器去支撐線上的一個請求。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章