使用Redis有哪些好處?
-
速度快
- 基於內存,避免了磁盤I/O的瓶頸。
- 單進程單線程,減少了線程上下文切換的開銷
- 利用隊列技術將並行訪問變為串行訪問,消除了傳統數據庫並發訪問控制鎖的開銷。
- Redis全程使用hash結構,讀取速度快,還有一些特殊的數據結構,對數據存儲進行了優化,如壓縮表,對短數據進行壓縮存儲,再如,跳表,使用有序的數據結構加快讀取的速度。
-
支持豐富的數據類型:支持string、list、set、sorted set、hash。
-
支持事務操作,保證操作原子性。
-
豐富的特性:可用於緩存、消息,按key設置過期時間,過期后將會自動刪除。
redis相比memcached有哪些優勢? (簡單了解一下memcached)
- memcached所有的值均是簡單的字符串,而redis支持更為豐富的數據類型。
- redis的速度比memcached快很多。
- redis可以支持持久化其數據。
redis常見性能問題和解決方案:
-
為了主從復制的速度和連接的穩定性,Master和Slave最好在同一個局域網內。
-
Master寫內存快照,save命令調度rdbSave函數,會阻塞主線程的工作,當快照比較大時對性能影響是非常大的,會間斷性暫停服務,所以Master最好不要寫內存快照。
-
Master AOF持久化,如果不重寫AOF文件,這個持久化方式對性能的影響是最小的,但是AOF文件會不斷增大,AOF文件過大會影響Master重啟的恢復速度。Master最好不要做任何持久化工作,包括內存快照和AOF日志文件,特別是不要啟用內存快照做持久化,如果數據比較關鍵,某個Slave開啟AOF備份數據,策略為每秒同步一次。
-
Master調用BGREWRITEAOF重寫AOF文件,AOF在重寫的時候會占大量的CPU和內存資源,導致服務load過高,出現短暫服務暫停現象。
Redis 最適合的場景
分布式鎖
Session緩存
參見58沈劍的干貨:session一致性架構設計實踐
排行榜/計數器
Redis在內存中對數字進行遞增或遞減的操作實現的非常好。集合(Set)和有序集合(Sorted Set)也使得我們在執行這些操作的時候變的非常簡單。所以,我們要從排序集合中獲取排名最靠前的10個用戶 —— 我們稱之為“user_scores”,我們只需要像下面一樣執行就可:
ZRANGE user_scores 0 10 WITHSCORES
發布/訂閱
Redis 發布訂閱(pub/sub)是一種消息通信模式:發送者(pub)發送消息,訂閱者(sub)接收消息。Redis客戶端可以訂閱任意數量的頻道。
下圖展示了頻道channel1,以及訂閱這個頻道的三個客戶端 —— Client1、Client2和Client5之間的關系:
當有新消息通過PUBLISH命令發送給頻道channel1時,這個消息就會被發送給訂閱它的三個客戶端:
MySQL里有2000w數據,redis中只存20w的數據,如何保證redis中的數據都是熱點數據
redis 內存數據集大小上升到一定大小的時候,就會施行數據淘汰策略。redis 提供 6種數據淘汰策略:
- voltile-lru:從已設置過期時間的數據集(server.db[i].expires)中挑選最近最少使用的數據淘汰。
- volatile-ttl:從已設置過期時間的數據集(server.db[i].expires)中挑選將要過期的數據淘汰
- volatile-random:從已設置過期時間的數據集(server.db[i].expires)中任意選擇數據淘汰
- allkeys-lru:從數據集(server.db[i].dict)中挑選最近最少使用的數據淘汰
- allkeys-random:從數據集(server.db[i].dict)中任意選擇數據淘汰
- no-enviction(驅逐):禁止淘汰數據
Redis為什么這么快?
-
純內存數據庫,避免了磁盤I/O的瓶頸。
-
單進程單線程,減少了線程上下文切換的開銷。
-
利用隊列技術將並行訪問變為串行訪問,消除了傳統數據庫並發訪問控制鎖的開銷。
-
Redis全程使用hash結構,讀取速度快,還有一些特殊的數據結構,對數據存儲進行了優化,如壓縮表,對短數據進行壓縮存儲,再如,跳表,使用有序的數據結構加快讀取的速度。
-
使用多路I/O復用模型,非阻塞I/O。
多路I/O復用模型:
多路I/O復用模型是利用 select、poll、epoll 可以同時監察多個流的 I/O 事件的能力,在空閑的時候,會把當前線程阻塞掉,當有一個或多個流有 I/O 事件時,就從阻塞態中喚醒,於是程序就會輪詢一遍所有的流(epoll 是只輪詢那些真正發出了事件的流),並且只依次順序的處理就緒的流,這種做法就避免了大量的無用操作。
這里“多路”指的是多個網絡連接,“復用”指的是復用同一個線程。采用多路 I/O 復用技術可以讓單個線程高效的處理多個連接請求(盡量減少網絡 IO 的時間消耗),且 Redis 在內存中操作數據的速度非常快,也就是說內存內的操作不會成為影響Redis性能的瓶頸,主要由以上幾點造就了 Redis 具有很高的吞吐量。
Redis為什么采用單線程?
我們首先要明白,上邊的種種分析,都是為了營造一個Redis很快的氛圍!官方FAQ表示,因為Redis是基於內存的操作,CPU不是Redis的瓶頸,Redis的瓶頸最有可能是機器內存的大小或者網絡帶寬。既然單線程容易實現,而且CPU不會成為瓶頸,那就順理成章地采用單線程的方案了(畢竟采用多線程會有很多麻煩!)。
可以參考:https://redis.io/topics/faq
看到這里,你可能會氣哭!本以為會有什么重大的技術要點才使得Redis使用單線程就可以這么快,沒想到就是一句官方看似糊弄我們的回答!但是,我們已經可以很清楚的解釋了為什么Redis這么快,並且正是由於在單線程模式的情況下已經很快了,就沒有必要在使用多線程了!
但是,我們使用單線程的方式是無法發揮多核CPU 性能,不過我們可以通過在單機開多個Redis 實例來完善!
這小結 參考自:為什么說Redis是單線程的以及Redis為什么這么快!
Redis 虛擬內存 (適用於value比key大的情況)
首先說明下redis的虛擬內存與操作系統虛擬內存不是一碼事,但是思路和目的都是相同的。就是暫時把不經常訪問的數據從內存交換到磁盤中,從而騰出寶貴的內存空間。對於redis這樣的內存數據庫,內存總是不夠用的。除了可以將數據分割到多個redis服務器以外。另外的能夠提高數據庫容量的辦法就是使用虛擬內存技術把那些不經常訪問的數據交換到磁盤上。如果我們存儲的數據總是有少部分數據被經常訪問,大部分數據很少被訪問,對於網站來說確實總是只有少量用戶經常活躍。當少量數據被經常訪問時,使用虛擬內存不但能提高單台redis數據庫服務器的容量,而且也不會對性能造成太多影響。redis沒有使用操作系統提供的虛擬內存機制而是自己在用戶態實現了自己的虛擬內存機制。
主要的理由有以下兩點:
-
操作系統的虛擬內存是以4k/頁為最小單位進行交換的。而redis的大多數對象都遠小於4k,所以一個操作系統頁上可能有多個redis對象。另外redis的集合對象類型如list,set可能存在於多個操作系統頁上。最終可能造成只有10%的key被經常訪問,但是所有操作系統頁都會被操作系統認為是活躍的,這樣只有內存真正耗盡時操作系統才會進行頁的交換。
-
相比操作系統的交換方式。redis可以將被交換到磁盤的對象進行壓縮,保存到磁盤的對象可以去除指針和對象元數據信息。一般壓縮后的對象會比內存中的對象小10倍。這樣redis的虛擬內存會比操作系統的虛擬內存少做很多IO操作。