https://www.zhihu.com/question/20734566
https://www.zhihu.com/question/19660689
http://blog.csdn.net/Ideality_hunter/article/details/77621643
redis和mysql要根據具體業務場景去選型
- mysql:數據放在磁盤
- redis:數據放在內存
redis適合放一些頻繁使用,比較熱的數據,因為是放在內存中,讀寫速度都非常快,一般會應用在下面一些場景
- 排行榜
- 計數器
- 消息隊列推送
- 好友關注,粉絲
那么為什么不直接全部用redis存儲呢?
我的看法是:因為redis存儲在內存中,如果存儲在內存中,存儲容量肯定要比磁盤少很多,那么要存儲大量數據,只能花更多的錢去購買內存,造成在一些不需要高性能的地方是相對比較浪費的,所以目前基本都是mysql(主) + redis(輔),在需要性能的地方使用redis,在不需要高性能的地方使用mysql,好鋼用在刀刃上
目前redis做數據庫還不太靠譜。它支持的數據類型太少,而且查詢功能太弱。redis並不是為了作為數據庫使用的,它更多地是一個高速存取器,一般用作緩存和類似場景。
如果你想找一個關系型數據庫如mysql的替代者,推薦使用mongodb,支持海量數據,查詢功能強大,數據類型支持廣泛。目前已有一些團隊在后台完全使用mongodb作為數據庫。======================
補充1:可以用SSDB代替(redis協議+leveldb存儲),生產環節若干 PCU百萬級項目用過。
補充2:看了下陌陌爭霸的方案,旁路存儲,如果覺得時間充足,也可以仿照實現。
補充3:把冷數據落地到mongo,熱數據在用redis存儲。
使用redis作為緩存,數據還需要存入數據庫中嗎?
我的答案是:
1redis只是緩存,不是數據庫如mysql,所以redis中有的數據庫,mysql中一定有。
2用戶請求先去請求redis,如果沒有,再去數據庫中去讀取。
3redis中緩存一些請求量比較大的數據(這些緩存數據,mysql中一定也是有的),沒必要所有數據都緩存到redis中。
5之所以從緩存中拿數據會快,是因為緩存的數據存在於內存中,不像mysql的數據是存在磁盤上的,即不用經過從磁盤加載到內存這個過程(這個過程是非常耗時和低效的),直接從內存獲取數據。
6當redis緩存崩潰的時候,那么不是海量的請求都去訪問數據庫了?數據庫能抗住嗎?
1)收下要分析,當成千億個請求同時訪問過來,數據庫為什么會扛不住?
①超大量的並發,數據庫扛不住。
舉個例子就明白了。
10000萬個plsql客戶端,同時訪問Oracle進行數據庫查詢、寫入等操作,數據庫肯定吃不消。
參考:http://blog.csdn.net/ideality_hunter/article/details/77621802
從這個角度來說,redis並不能幫什么忙。
②數據庫存在低速設備上,每次訪問數據庫,都要經過io,即從磁盤調入內存的過程。這個才是使用redis等緩存機制的原因。
2)當redis奔潰了,成千億個請求同時訪問過來,數據庫扛不住,該怎么辦?
=====解答某些同學的提問,核心是,redis中存的數據,數據庫中是否還要存的問題。
我的觀點:
1前提:mysql中存all即所有的數據(redis只是緩存的mysql中的部分數據),redis中緩存mysql中存在的訪問量超級大的數據。
2如果redis中沒有我要的數據,那么其實這些請求並發量沒有那么大(為什么?參看上面的前提),那么就去mysql訪問,肯定並沒有太大壓力。
反方觀點1:既然redis中存了,數據庫為什么還要存呢?所以他們認為數據存入redis就不用存數據庫了。
反方觀點2:如果redis崩潰了,緩存丟失了,不是所有的請求都壓到mysql了?mysql數據是存在硬盤上的,讀取是低速的,mysql肯定扛不住。
我的解答:
解答反方觀點1:這個不用爭,redis是當緩存用的,不是當數據庫用的。
解答反方觀點2:我承認mysql這種情況下肯定扛不住,但是你全把數據放入redis風險不就更大了嗎?因為我雖然慢,但是最起碼沒有丟失,但是你redis是放入內存的,所有數據都丟失了?
反方觀點3:我的redis數據並沒有丟啊,redis有災備機制,因為redis會將其中的數據實時地存入磁盤,這樣就不怕丟了。
解答反方觀點3:那這不是回到我的思路上了嗎?你存磁盤其實跟存數據庫不是一個道理嗎?方正都是存磁盤?你怎么能將99G或者更大的數據快速的從磁盤加載到redis即內存中呢?不可能的。
所以,咱們兩種方式其實都是一樣的,都解決不了,如果redis即內存崩潰了,然后重啟redis之后,怎么快速的響應千萬甚至過億的請求。
我的方式:redis壞了,從數據庫讀取。
你的方式:redis壞了,從磁盤慢慢地恢復到redis,然后從redis讀取。
反方觀點5:如果redis崩潰了,我不光可以放入磁盤一種方式,我還可以放入所在集群中的其他機器如B的內存中啊,這樣如果機器A的redis崩潰了,只需要去訪問機器B的內存中去取所需要的內容即可。
解答反方觀點5:①這種方式我沒研究過,集群,竟然內存也是共享的?②就算你說的是對的,我的那種方式,也完全可以融入你的機制,如果redis崩潰了,也將數據轉移到集群中的B的內存中。這樣的話,咱倆的方式其實就一樣了。
反方觀點6:你如果也采取我的那種方式,將數據轉移到集群中的其他機器的內存中,那么為什么還要再存入mysql中一份呢,完全沒有必要,因為對於這部分數據,根本不會去mysql中去讀取的,一直是在redis中讀取就行了。
解答反方觀點6:你是對的,我無言以對。但是我質疑你說的將數據轉移到集群中其他機器上這種方式的可行性。
我對反方觀點5的質疑:照你你這種機制,其實就可以不用硬盤了,你用內存就行了,你可以把所有的數據都存入redis了,還將用戶等信息放入mysql中干什么?
反方解答我的質疑:mysql中存的是不經常訪問的事情。
總結:
的確, 如果可以實現A機器崩潰時可以將redis中的數據轉移到集群中機器B的內存中(我對這種方式的可行性是質疑的),那么,數據存入redis就可以不用存入mysql,但是這就顛覆了我及常人對緩存的理解,這其實就不是什么緩存,而是直接將redis當數據庫來用了。
竟然還真有這種方式:
https://www.zhihu.com/question/21419897
