文章原創於公衆號:程序猿周先森。本平臺不定時更新,喜歡個人文章,歡迎關注個人微信公衆號。
面試
實際項目開發中如今沒法逃避的一個問題就是緩存問題,而緩存問題也是面試必問知識點之一,若是面試官好一點可能會簡單的問你二八定律或者熱數據和冷數據,可是若是問的深刻一點可能就會問到緩存更新、降級、預熱、雪崩、穿透等問題,而這些問題可能會攔下大部分平時不怎麼關注緩存的朋友,這些問題實際上都和緩存服務器息息相關,咱們平常中常用的緩存服務器通常有兩種:Redis和Memcached。本篇開始正式進入Redis系列文章,本篇主要講講Redis使用單線程爲什麼速度還能如此之快?redis
既然談到緩存服務器有兩種,那咱們爲什麼要選擇Redis呢?Redis與Memcached二者之間有何區別呢?數據庫
Redis 和 Memcached 的區別緩存
Redis是一個key-value存儲系統。它支持存儲的value類型相對更多,包括string(字符串)、list(鏈表)、set(集合)、zset(有序集合)和hash(哈希類型)。這些數據類型都支持push/pop、add/remove及取交集並集和差集及更豐富的操做,並且這些操做都是原子性的。在此基礎上,redis支持各類不一樣方式的排序。爲了保證效率,數據都是緩存在內存中。區別的是redis會週期性的把更新的數據寫入磁盤或者把修改操做寫入追加的記錄文件,而且在此基礎上實現了主從同步。簡單來講 Redis 就是一個數據庫,不過與傳統數據庫不一樣的是 Redis 的數據是存在內存中的,因此存寫速度很是快,所以 Redis 被普遍應用於緩存方向。Redis 也常常用來作分佈式鎖。Redis 提供了多種數據類型來支持不一樣的業務場景。除此以外,Redis 支持事務 、持久化、LUA 腳本、LRU 驅動事件、多種集羣方案。Redis中經常使用的數據類型實際上只有5種:String、Hash、List、Set、ZSet,咱們能夠先看下這五種基本數據類型的用法:服務器
String微信
String 數據結構是簡單的 Key-Value 類型,Value 能夠是string或者數字。常規 Key-Value 緩存應用;常規計數:博客數,閱讀數等。網絡
Hash數據結構
Hash 特別適合用於存儲對象。多線程
List併發
鏈表是 Redis 最重要的數據結構之一,Redis List 爲一個雙向鏈表,支持反向查找和遍歷,更方便操做,不過帶來了額外的內存開銷。
Set
Set 其實和List都是列表的選項,Set 是能夠自動去重的。當須要存儲一個不出現重複數據的列表數據,Set 是一個最好的選擇。你能夠基於 Set 輕易實現交集、並集、差集的操做。
Sorted Set
Sorted Set 相比Set增長了一個權重參數 Score,使得集合中的元素可以按 Score 進行有序排列。
數據庫工做模式若是按照存儲方式進行劃分能夠分紅兩種:硬盤數據庫和內存數據庫。Redis讀寫數據之因此如此之快實際上就是因爲Redis將數據存儲在內存中,因此在讀寫數據時不會受到硬盤I/O速度限制,因此讀寫速度天然很快。而硬盤數據庫則是在內存中儲存一個索引,而後根據索引去硬盤中查詢對應的值,因此效率確定會相對更慢。
Redis基於內存採用單線程單進程模型的Key-Value數據庫,通過官方測試每秒查詢次數能夠高達100000+,那爲何Redis如此快呢?最關鍵的一點其實剛纔已經提到過,由於Redis徹底基於內存,Redis接收到的大部分請求都是直接操做內存就能夠完成的,因此處理請求很是迅速,並且Redis中使用單線程,避免了沒必要要的上下文切換和競爭鎖機制,也不會出現頻繁切換線程致使CPU消耗,不會存在多線程的死鎖等一系列問題。在Redis中使用多路複用I/O模型,而不是非阻塞I/O,非阻塞I/O以前在Nginx提到過,因此咱們不重複介紹,咱們重點看看多路I/O複用模型。
多路I/O複用模型其實是使用select、poll、epoll同時監聽多個流的I/O事件,在無I/O事件時也就是空閒狀態下會將線程阻塞,當有I/O事件須要處理時,線程就是從阻塞狀態下喚醒,而後使用epoll輪詢一遍全部發生I/O事件的流。多路複用實際上還就是說多個網絡鏈接複用同一個線程,採用多路I/O複用技術可讓單個進程高效的處理多個鏈接請求,且Redis在內存中對數據進行操做,因此數據操做速度很是快,因此速度不會受到瓶頸,因此Redis才能夠具備很高的吞吐量及性能。Redis的瓶頸主要來源於機器內存或網絡帶寬,CPU不是Redis的瓶頸所在,再加上單線程更易於實現,因此瓜熟蒂落Redis採用單線程的方式,可是使用單線程的方式是沒法發揮多核CPU的優點的,好比在進行比較耗時的操做時會使得Redis併發量降低,由於單線程因此某一時刻只能處理一個操做,因此執行耗時操做會致使併發量的降低,有一個簡單的解決方案就是在多核CPU下能夠單機開多個Redis實例來解決這個問題。
歡迎關注公衆號:程序猿周先森。