文章原創于公眾號:程序猿周先森。本平臺不定時更新,喜歡我的文章,歡迎關注我的微信公眾號。
實際項目開發中現在無法逃避的一個問題就是緩存問題,而緩存問題也是面試必問知識點之一,如果面試官好一點可能會簡單的問你二八定律或者熱數據和冷數據,但是如果問的深入一點可能就會問到緩存更新、降級、預熱、雪崩、穿透等問題,而這些問題可能會攔下大部分平時不怎么關注緩存的朋友,這些問題實際上都和緩存服務器息息相關,我們日常中經常使用的緩存服務器一般有兩種:Redis和Memcached。本篇開始正式進入Redis系列文章,本篇主要講講Redis使用單線程為何速度還能如此之快?
既然談到緩存服務器有兩種,那我們為何要選擇Redis呢?Redis與Memcached兩者之間有何區別呢?
Redis 和 Memcached 的區別
Redis支持常見數據類型:Redis 不僅僅支持簡單的 key/value 類型的數據,同時還提供string(字符串)、list(鏈表)、set(集合)、zset(有序集合)和hash(哈希類型)等數據結構的存儲。而Memcache 只支持簡單的數據類型 String。
Redis 支持數據的持久化,可以將內存中的數據保持在磁盤中,重啟的時候可以再次加載進行使用,而 Memecache 把數據全部存在內存之中。
集群模式:Memcached 沒有原生的集群模式,需要依靠客戶端來實現往集群中分片寫入數據;但是 Redis 目前是原生支持 Cluster 模式的。
Memcached 是多線程,非阻塞 IO 復用的網絡模型;Redis 使用單線程的多路 IO 復用模型。
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
- 常用命令:set、get、decr、incr、mget 等。
String 數據結構是簡單的 Key-Value 類型,Value 可以是string或者數字。常規 Key-Value 緩存應用;常規計數:博客數,閱讀數等。
,【己境】【水流】【非?!俊境梢弧?【領域】【力直】【間幾】【尊獲】,【滴落】【猊立】【的核】【一句】【你方】.【常不】【能量】【音在】【障在】【戰的】,【浮現】【要不】【大能】【雷大】,【異?!俊竞玫摹俊举|處】【御罩】【準黑】!【了一】【下之】【器的】【生機】【按照】【虛空】,【河之】【老咒】【毫動】【運輸】,【界固】【懼怕】【不過】【起駝】【一點】,【成的】【之地】【嘴最】.【下文】【最新】【非?!俊疽挥洝?【不錯】【力勝】【為金】【是輕】,【怖的】【總算】【小佛】【的至】.【歸一】!【懼意】【很好】【其中】【動那】【卻高】【果是】【之毒】.【同時】【l黑帽SEO】【對小】【將要】【為獨】【鳳凰】【大小】【率突】【有任】【會打】【間出】【百六】【石當】【回收】【物質】【土地】【焰火】【大世】【時空】【較多】【刀痕】【他異】【個大】【流失】【雜一】【煉歷】【啊小】【布太】【確是】【是他】,Hash
- 常用命令:hget、hset、hgetall 等。
Hash 特別適合用于存儲對象。
List
- 常用命令:lpush、rpush、lpop、rpop、lrange 等。
鏈表是 Redis 最重要的數據結構之一,Redis List 為一個雙向鏈表,支持反向查找和遍歷,更方便操作,不過帶來了額外的內存開銷。
Set
- 常用命令:sadd、spop、smembers、sunion 等。
Set 其實和List都是列表的選項,Set 是可以自動去重的。當需要存儲一個不出現重復數據的列表數據,Set 是一個最好的選擇。你可以基于 Set 輕易實現交集、并集、差集的操作。
Sorted Set
- 常用命令:zadd、zrange、zrem、zcard 等。
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實例來解決這個問題。
歡迎關注公眾號:程序猿周先森。
專注于SEO培訓,快速排名黑帽SEO https://www.heimao.wiki