03.04 Redis如何彌補傳統MySQL架構的不足?

VIP-linxi


Mysql是一款開源免費,使用最多的非關係型數據庫,體積小,性能強大,查詢速度快!

但是大多數關係型數據庫的數據都是存儲在計算機硬盤上的,數據在磁盤存取的時候是機械操作,斷電不丟失數據,而內存是存儲電信號,斷電就丟失數據,內存的存取速度比硬盤的存取速度快了很多很多!


mysql數據也是存在硬盤,存取速度相對於存在內存的redis有很大差距,在高併發環境,如果有瞬間的大量請求通過,則mysql會存在存取速度慢導致系統崩潰的情況!

比如說秒殺場景,在一秒鐘之內,有可能有數百萬的數據訪問,而mysql是完全不能處理的,對這種場景可使用內存型數據庫,比如redis,先將需要秒殺的商品ID存入到redis中,將商品ID和用戶的信息異步保存到數據庫,減少數據庫的衝擊!

再比如一個場景,某個產品非常熱門,大量的客戶端在訪問這個產品的詳情,這時候可以把這個數據的詳情緩存到redis中,可以減少大量的訪問數據庫,提升整個系統的吞吐性能!


由此可見,其實緩存就是相當於數據庫的限流工具!

不過,緩存加數據庫的果架構也會存在問題,如緩存擊穿,緩存穿透,緩存雪崩,這些事故的發生可能是因為緩存突然宕機,也可能是因為程序設置不當導致緩存失效,進而大量的數據請求衝擊數據庫,引發數據庫崩潰!

針對這種情況,應該做到以下幾點:

1,儘量使用緩存集群,防止單機宕機引發的緩存失效!

2,防止大量數據庫key同時失效的情況!

3,對key進行合理性檢驗,防止攻擊!(比如數據庫ID一般來說都是正整數吧,別人使用一個負數一直來查詢,這樣所有的請求都落在了數據庫)!


總之,在高併發環境,緩存極大的釋放了數據庫的壓力,提升了整個系統的性能,我對JAVA相關技術算是比較瞭解,以後也會一直分享,歡迎關注,互相溝通!


此生唯一


談一下我的理解,如果有不對的地方,請留言指正。


MySQL+Redis

Redis自身是可以做數據持久化的,很多同學都會想Redis應該可以替代MySQL,但是我們使用一項技術、一個框架的時候,不是看它能不能,而是要看它適合不適合。

所以大多數公司的存儲都是MySQL+Redis,MySQL(或者其他關係型數據庫)作為主存儲,Redis作為輔助存儲,被用作緩存,這樣可以加快訪問讀取的速度,提高性能。



Redis被用作緩存,以減少數據庫IO的讀操作,減輕數據庫的壓力,例如:

  • 存儲熱點數據:經常會被查詢,但是不經常被修改或者刪除的數據;

  • 計數器:諸如很多論壇用於統計點擊數;

  • 分佈式鎖及單線程機制;

  • 最新列表、排行榜:請不要使用select top 10 from xxxx。


劃重點,下面介紹一下緩存穿透

很多時候,程序員習慣先查詢Redis,查詢不到的話再去查詢數據庫,能查到的話再寫入Redis中,認為這樣不僅緩解了數據庫的壓力,同時也能保證數據的準確性。

但是由於緩存不命中就會查詢數據庫,如果一直查詢不到的話,就導致每次請求都會查詢數據庫,如果短時間內有大量這樣的請求,那麼數據庫可能會扛不住。


這就是緩存穿透。

其實應對的方法也很簡單,查詢不到的數據,也緩存到Redis中,並設置數據的過期時間。

舉個不一定恰當的例子,例如Redis中緩存員工信息,提供接口根據工號查詢員工信息:

  1. 接口入參工號A001。

  2. 系統先在Redis中查詢,查詢不到。

  3. 系統去數據庫中查詢,也查詢不到。

  4. 系統插入Redis,key=A001,value=null,設置過期時間五分鐘。


  5. 這樣,五分鐘之內再根據A001查詢,不會穿透到數據庫。

  6. 四分鐘後,數據庫中插入了A001的數據。

  7. 五分鐘後,Redis中數據過期,下一次請求過來,會查詢數據庫,並把信息加載到Redis中。



希望我的回答,能夠幫助到你!

我會持續分享Java程序開發、架構設計、職業發展等方面的知識和見解,希望能得到你的關注今日頭條【會點代碼的大叔】,轉載請註明出處。


會點代碼的大叔


使用的就是Redis+MySql來互相輔助。

MySQL的優勢

首先,我們必須承認Mysql作為關係型數據庫管理系統有其不可代替的優勢,主要體現在以下5個方面。

1 支持處理大量數據,量級可達到八位數

2 支持常見的SQL語句規範

3 可移植性強,安裝起來小巧方便

4 運行效率高

5 使用量大,能夠獲得廣泛的網絡信息支持

基於此,MySQL通常作為持久層,出現在各種web應用場景。

MySQL的侷限性

但是當表內數據量很大之後,如果不加索引,其查詢效率將有驚人的衰退。

我們通常默認查詢語句是毫秒級別的返回,但是我在實際工作中曾經遇到過一張包含10個字段的表,900萬+條數據。當根據一個未加索引的字段進行精確查詢的時候,單條sql語句的執行時長有時能夠達到2min以上,就更別提如果用like這種模糊查詢的話,其效率將會多麼低下。

也許你會說,那再對該字段加一個索引好了。

如果你真的這麼做了,恭喜你,你踩了一個比大查詢還可怕的坑。

假設我們使用的Mysql已經是主從庫了,那麼大查詢語句執行很久時,卡住的頂多是從庫,主庫還是不受任何影響的。但是如果此時你又執行了增加索引操作,那麼主庫將會對這900萬+條數據依次操作增加索引,結果就是主庫從庫全部卡住,此時所有請求,不論增刪改查,全部hang住,等待查詢與增加索引操作執行結束。從用戶的角度,感受到的就是服務響應變慢,甚至超時。

Redis的優勢如何彌補Mysql

在這種時刻,Redis的重要性就體現出來了。

Redis具有讀寫速度極快,支持多種存儲類型,支持事務以及分佈式鎖的優勢。

與上面的侷限性結合起來看就可以看出,Redis能夠彌補MySQL讀寫慢的劣勢,對於一些無需持久化的數據,或者是在持久化之前會頻繁變動的數據,就可以選擇用Redis做緩存。

舉個例子,我創建了一個任務數據Task,這個Task在最終完成寫入數據庫之前,有很多個步驟需要改變Task的屬性值,在這個過程中,將Task持久化數據庫是無意義的,反而會徒增很多讀寫的步驟,浪費執行時間。如果選擇在創建Task之後,就將其寫入數據庫與Redis,在中間過程,只讀寫Redis中Task的值,在完成Task之後,確認其值不會改變後,再持久化入MySql,就能夠極大的提高系統的效率。

這樣,就能夠將原本給Mysql的讀寫壓力,分配到了Redis上。

Redis無法取代Mysql

雖然Redis的讀寫速度優於MySQL,並且支持配置持久化,但是沒有任何一個對外應用匯選擇Redis來代替MySQL。

主要原因是Redis持久化數據是需要一定代價的。我們曾親身經驗過一次事件,我們一個服務的Redis節點誤開啟了持久化開關,重啟節點後,幾分鐘都無法讀取,最開始我們以為是服務器的問題,網絡問題,最後通過日誌才發現,是由於Redis重啟後,要load持久化的數據進來,儘管這個數據量遠遠小於MySQL存儲的數據,但是啟動時長卻用了分鐘級別。

此外,Redis不支持sql語句,當數據量增加後,其讀寫效率也會顯著下降等問題,也是它無法代替MySQL的原因。


綜上,最科學的方法是用MySQL+Redis的結合,分攤數據讀寫壓力,從而提高系統效率。


以上是我個人經驗,如果對你有幫助,請順手送個贊給我,或者在下方評論區留言給我。



我是蘇蘇思量,頭像是本人,來自BAT的java工程師,經常分享科技類見聞,歡迎關注我,與我互動。


一個存在感小透明


大聲反對樓下說的Redis做主庫。

Redis要求內存,你想想你們的數據量增長態勢,先算一下內存夠不夠用。

Redis的持久化有問題,想保證數據不丟時使用AOF模式(注:AOF持久化策略是將發送到Redis服務端的每一條命令都記錄下來,並且保存到硬盤中的AOF文件中,類似打日誌文件,來一條命令就記錄一條),策略為fsync always,這種的性能比Mysql還低!如果你喜歡它直觀的kv結構而對性能要求不高,或者性能要求很高,但允許一定程度的丟失數據,則可以用redis做為主數據庫。你真的考慮好了嗎?你能確定丟了什麼數據嗎?Redis做主數據庫是不靠譜的,並不是所有的數據都是立即回寫磁盤!

它適合小數據量重複查詢,實時要求高的地方,項目中主要是做高速緩存和session狀態存儲等,其作為Nosql數據庫,多條件聯合查詢效率低,操作不便,主要數據結構不夠豐富,int,date之類也沒有,主庫還是採用成熟的Mysql比較好。

如何彌補不足?

主要是它適合存儲一些不是特別緊要的比如關注,粉絲關係,等等可以直接轉換為kv格式的數據,能夠避免頻繁查詢數據庫給數據庫造成的壓力。可以做一些數據聚合和統計工作,這些都允許少量的數據丟失,網站今天有12800人訪問和12795人訪問,對老闆來說都是一樣的。Redis還有特別的地理關係數據結構,適合做附近關係等等。

總結下來就是三方面,一方面做緩存,扛住訪問關係型數據庫的壓力。二是做運營推廣時效性活動,數據聚合統計工作的,可以全放在Redis,有對應的數據結構可用。三是地理位置等特殊用途。

每種數據庫都有它合適的位置,眉毛鬍子一把抓不可取。

如果您認同我的觀點,請點擊右上角紅字“關注”,謝謝。


小七讀書漲知識


Redis本身有固化機制,完全可以當作主數據庫使用,如果對事務要求不高的話。和MySQL配合用,可以把MySQL當作Redis後備庫,業務數據放在Redis中運行,用異步方式寫入MySQL。Redis的優點是可以任意做鏡像,可以集群。Redis當主庫使用,必須要保證至少一個異地Slave,防止主庫當機時丟失數據。


光明右使8787


redis把數據存在內存,效率高。mysql每次查詢要有io性能差,redis可以減少服務器壓力。


分享到:


相關文章: