經過前面關於Redis五種數據類型、相關高級特性以及一些簡單示例的使用,對Redis的使用和主要的用途應該有所掌握,可是還有一些原理性的問題咱們在本部分作一個探討。html
本部分參考了一些其餘博客,在文後的參考連接中註明,特此說明。mysql
Redis是一種Key-value型的存儲數據庫,咱們天然有一個疑惑,咱們早已會用相似於mysql這樣的關係型數據庫了,那麼他們之間有什麼區別,爲何還要用Redis。nginx
(1)數據庫類型不一樣redis
mysql是咱們熟知的關係型數據庫,數據嚴格存儲在表格的行和列中,面向的是結構化的數據。而Redis是一種非關係型數據庫,屬於一種NoSQL數據庫,除告終構化數據,還能夠存儲半結構化和非結構化的數據,好比咱們在數據類型中提到,字符串能夠存儲任何數據,好比jpg圖片或者序列化的對象。sql
(2)運行機制不一樣數據庫
mysql主要用於存放持久化的數據,將數據存放在硬盤中,讀取速度比較慢,適合存放大數據。Redis的數據保存在緩存中,緩存的讀取速度快,效率高,要存放大量數據須要進行分區和橫向擴展。另外,Redis天生就是適合分佈式存儲的,能夠動態的橫向擴展。編程
mysql在每次訪問數據庫時,都存在着複雜的I/O操做,在鏈接數據庫上花費大量時間,效率比較慢。Redis的數據自己就在緩存中,能夠用於存儲使用頻繁的熱數據,不會產生複雜的I/O。緩存
(3)面向的需求不一樣安全
mysql面向大量數據的持久化存儲,因爲關係型數據庫的優點,適合用於多表聯合查詢等。Redis因爲緩存容量有限,只能夠做爲一個減輕數據庫壓力的緩衝和少許熱數據存儲的數據庫。所以,實際上,不少狀況下是mysql和Redis聯合使用,redis存儲使用頻繁的數據,這樣減小訪問數據庫的次數,提升運行效率。網絡
(4)性能差別明顯
關係型數據庫爲了維護數據的一致性付出了巨大的代價,讀寫性能比較差。在面對高併發讀寫性能很是差,面對海量數據的時候效率很是低。而Nosql存儲的格式都是key-value類型的,而且存儲在內存中,很是容易存儲,並且對於數據的 一致性是 弱要求。Nosql無需sql的解析,提升了讀寫性能。
關於爲何使用Redis,感受有一篇博客講的比較好,這裏借用其中的兩幅圖(參考連接中註明)。
使用Redis主要考慮到的是兩個因素:性能和併發。
(1)高性能
在碰到須要執行耗時特別久,且結果不頻繁變更的SQL,就特別適合將運行結果放入緩存。這樣,後面的請求就去緩存中讀取,使得請求可以迅速響應。
(2)高併發
在大併發的狀況下,全部的請求直接訪問數據庫,數據庫會出現鏈接異常。這個時候,就須要使用redis作一個緩衝操做,讓請求先訪問到redis,而不是直接訪問數據庫。
(1) 絕大部分請求是純粹的內存操做(很是快速)
(2) 採用單線程,避免了沒必要要的上下文切換和競爭條件
(3) 非阻塞多路IO複用
單線程指的是網絡請求模塊使用了一個線程(因此不需考慮併發安全性),即一個線程處理全部網絡請求,其餘模塊仍用了多個線程。
這個可能不太好理解,單線程怎麼還比多線程快了呢,這是由於Redis的性能瓶頸在內存的大小和網絡的帶寬,重點是Redis存儲在內存,不涉及I/O操做,(只有在有I/O操做的時候,線程由於I/O而阻塞,此時將CPU讓給別的線程會達到比較好的性能),因此Redis幾乎不涉及任何的外部I/O,所以,單線程是最快的。
IO多路複用是用來解決對多個I/O監聽時,一個I/O阻塞影響其餘I/O的問題,跟多線程不要緊。跟多線程相比較,線程切換須要切換到內核進行線程切換,須要消耗時間和資源.而I/O多路複用不須要切換線/進程,效率相對較高,特別是對高併發的應用nginx就是用I/O多路複用,故而性能極佳.但多線程編程邏輯和處理上比I/O多路複用簡單.而I/O多路複用處理起來較爲複雜。
這個理解較難,能夠參考文後給出的連接。
redis採用的是按期刪除+惰性刪除策略。
按期刪除,redis默認每一個100ms檢查,是否有過時的key,有過時key則刪除。須要說明的是,redis不是每一個100ms將全部的key檢查一次,而是隨機抽取進行檢查(若是每隔100ms,所有key進行檢查,redis豈不是卡死)。所以,若是隻採用按期刪除策略,會致使不少key到時間沒有刪除。因而,惰性刪除派上用場。也就是說在你獲取某個key的時候,redis會檢查一下,這個key若是設置了過時時間那麼是否過時了?若是過時了此時就會刪除。
若是按期刪除沒刪除key。而後你也沒即時去請求key,也就是說惰性刪除也沒生效。這樣,redis的內存會愈來愈高。那麼就應該採用內存淘汰機制。
在redis.conf中有一行配置maxmemory-policy allkeys-lru
,該配置就是配內存淘汰策略的。
1)noeviction:當內存不足以容納新寫入數據時,新寫入操做會報錯。
2)allkeys-lru:當內存不足以容納新寫入數據時,在鍵空間中,移除最近最少使用的key。推薦使用。
3)allkeys-random:當內存不足以容納新寫入數據時,在鍵空間中,隨機移除某個key。
4)volatile-lru:當內存不足以容納新寫入數據時,在設置了過時時間的鍵空間中,移除最近最少使用的key。
5)volatile-random:當內存不足以容納新寫入數據時,在設置了過時時間的鍵空間中,隨機移除某個key。
6)volatile-ttl:當內存不足以容納新寫入數據時,在設置了過時時間的鍵空間中,有更早過時時間的key優先移除。
http://www.javashuo.com/article/p-hlxqtctl-hw.html
http://www.javashuo.com/article/p-cakqnuif-ka.html
https://www.jianshu.com/p/9b71f8ee6e28
做者:itcats_cn
來源:CSDN
原文:http://www.javashuo.com/article/p-wfxrgmxd-q.html