一、Redis簡介
·?Redis官網:https://redis.io/
·?Redis是一種基于鍵值對(key-value)的NoSQL數據庫
·?與很多鍵值對數據庫不同的是,Redis中的值可以是由string(字符串)、hash(哈希)、 list(列表)、set(集合)、zset(有序集合)、Bitmaps(位圖)、 HyperLogLog、GEO(地理信息定位)等多種數據結構和算法組成,因此 Redis可以滿足很多的應用場景,
·?而且因為Redis會將所有數據都存放在內存中,所以它的讀寫性能非常驚人。不僅如此,Redis還可以將內存的數據利用快照和日志的形式保存到硬盤上,這樣在發生類似斷電或者機器故障的時候,內存中的數據不會“丟失”
·?除了上述功能以外,Redis還提供了鍵過 期、發布訂閱、事務、流水線、Lua腳本等附加功能
Redis與其他數據庫的對比??
附加
·?Redis提供了幾十種不同編程語言的客戶端庫,這些庫都很好地封裝了Redis的命令,使得在程序中與 Redis 進行交互變得更容易。有些庫還提供了可以將編程語言中的數據類型直接以相應的形式存儲到Redis中(如將數組直接以列表類型存入Redis)的簡單方法,使用起 來非常方便
·?Redis使用C語言開發,代碼量只有3萬多行。這降低了用戶通過修改Redis源代碼來使之更適合自己項目需要的門檻。對于希望“榨干”數據庫性能的開發者而言,這無疑是一個很大的吸引力
·?Redis是開源的,所以事實上 Redis的開發者并不止Salvatore Sanfilippo 和 Pieter Noordhuis。截至目前,有將近100名開發者為Redis貢獻了代碼。良好的開發氛圍和嚴謹的版 本發布機制使得Redis的穩定版本非常可靠,如此多的公司在項目中使用了 Redis 也可以印 證這一點
·?Redis完整的命令列表可以在:https://redis.io/commands中找到
二、Redis的特性
①速度快
·?正常情況下,Redis執行命令的速度非常快,官方給出的數字是讀寫性能可以達到10萬/秒,當然這也取決于機器的性能,但這里先不討論機器性能上的差異,只分析一下是什么造就了Redis除此之快的速度,可以大致歸納為以下四點:
·?Redis的所有數據都是存放在內存中的,下圖是谷歌公司2009年給出的各層級硬件執行速度,所以把數據放在內存中是Redis速度快的最主要原因
·?Redis是用C語言實現的,一般來說C語言實現的程序“距離”操作系統更 近,執行速度相對會更快
·?Redis使用了單線程架構,預防了多線程可能產生的競爭問題
②基于鍵值對的數據結構服務器?
·?幾乎所有的編程語言都提供了類似字典的功能,例如Java里的map、 Python里的dict,類似于這種組織數據的方式叫作基于鍵值的方式
·?與很多鍵值對數據庫不同的是,Redis中的值不僅可以是字符串,而且還可以是具體的數據結構,這樣不僅能便于在許多應用場景的開發,同時也能夠提高開發效率
·?Redis的全稱是REmote Dictionary Server,它主要提供了5種數據結 構:字符串、哈希、列表、集合、有序集合,同時在字符串的基礎之上演變出了位圖(Bitmaps)和HyperLogLog兩種神奇的“數據結構”,并且隨著 LBS(Location Based Service,基于位置服務)的不斷發展,Redis3.2版本中加入有關GEO(地理信息定位)的功能
·?總之在這些數據結構的幫助下,開 發者可以開發出各種“有意思”的應用
③豐富的功能
·?除了5種數據結構,Redis還提供了許多額外的功能:
·?提供了鍵過期功能,可以用來實現緩存
·?提供了發布訂閱功能,可以用來實現消息系統
·?支持Lua腳本功能,可以利用Lua創造出新的Redis命令
·?提供了簡單的事務功能,能在一定程度上保證事務特性
·?提供了流水線(Pipeline)功能,這樣客戶端能將一批命令一次性傳到 Redis,減少了網絡的開銷
④簡單穩定
·?Redis的簡單主要表現在三個方面:
·?首先,Redis的源碼很少,早期版本 的代碼只有2萬行左右,3.0版本以后由于添加了集群特性,代碼增至5萬行 左右,相對于很多NoSQL數據庫來說代碼量相對要少很多,也就意味著普通的開發和運維人員完全可以“吃透”它
·?其次,Redis使用單線程模型,這樣 不僅使得Redis服務端處理模型變得簡單,而且也使得客戶端開發變得簡 單
·?最后,Redis不需要依賴于操作系統中的類庫(例如Memcache需要依賴 libevent這樣的系統類庫),Redis自己實現了事件處理的相關功能
·?Redis雖然很簡單,但是不代表它不穩定。以筆者維護的上千個Redis為例,沒有出現過因為Redis自身bug而宕掉的情況
⑤客戶端語言多
·?Redis提供了簡單的TCP通信協議,很多編程語言可以很方便地接入到Redis,并且由于Redis受到社區和各大公司的廣泛認可,所以支持Redis的客 戶端語言也非常多,幾乎涵蓋了主流的編程語言,例如Java、PHP、 Python、C、C++、Nodejs等
·?可參閱:http://redis.io/clients
⑥持久化
·?通常看,將數據放在內存中是不安全的,一旦發生斷電或者機器故障, 重要的數據可能就會丟失,因此Redis提供了兩種持久化方式:RDB和 AOF,即可以用兩種策略將內存的數據保存到硬盤中,這樣就保證了數據的可持久性
⑦主從復制
·?Redis提供了復制功能,實現了多個相同數據的Redis副本,復制功能是分布式Redis的基礎
⑧高可用和分布式
·?Redis從2.8版本正式提供了高可用實現Redis Sentinel,它能夠保證Redis節點的故障發現和故障自動轉移
·?Redis從3.0版本正式提供了分布式實現 Redis Cluster,它是Redis真正的分布式實現,提供了高可用、讀寫和容量的擴展性
三、Redis的使用場景
Redis可以做什么?
·?緩存
·?緩存機制幾乎在所有的大型網站都有使用,合理地使用緩存不僅可以加 快數據的訪問速度,而且能夠有效地降低后端數據源的壓力。Redis提供了 鍵值過期時間設置,并且也提供了靈活控制最大內存和內存溢出后的淘汰策 略。可以這么說,一個合理的緩存設計能夠為一個網站的穩定保駕護航
·?排行榜系統
·?排行榜系統幾乎存在于所有的網站,例如按照熱度排名的排行榜,按照 發布時間的排行榜,按照各種復雜維度計算出的排行榜,Redis提供了列表 和有序集合數據結構,合理地使用這些數據結構可以很方便地構建各種排行榜系統。
·?計數器應用
·?計數器在網站中的作用至關重要,例如視頻網站有播放數、電商網站有 瀏覽數,為了保證數據的實時性,每一次播放和瀏覽都要做加1的操作,如 果并發量很大對于傳統關系型數據的性能是一種挑戰。Redis天然支持計數 功能而且計數的性能也非常好,可以說是計數器系統的重要選擇。
·?社交網絡
·?贊/踩、粉絲、共同好友/喜好、推送、下拉刷新等是社交網站的必備功能,由于社交網站訪問量通常比較大,而且傳統的關系型數據不太適合保存 這種類型的數據,Redis提供的數據結構可以相對比較容易地實現這些功 能
·?消息隊列系統
·?消息隊列系統可以說是一個大型網站的必備基礎組件,因為其具有業務 解耦、非實時業務削峰等特性。Redis提供了發布訂閱功能和阻塞隊列的功 能,雖然和專業的消息隊列比還不夠足夠強大,但是對于一般的消息隊列功 能基本可以滿足
Redis不可以做什么?
·?實際上和任何一門技術一樣,每個技術都有自己的應用場景和邊界,也 就是說Redis并不是萬金油,有很多適合它解決的問題,但是也有很多不合 適它解決的問題。我們可以站在數據規模和數據冷熱的角度來進行分析
·?站在數據規模的角度看,數據可以分為大規模數據和小規模數據,我們知道Redis的數據是存放在內存中的,雖然現在內存已經足夠便宜,但是如果數據量非常大,例如每天有幾億的用戶行為數據,使用Redis來存儲的話,基本上是個無底洞,經濟成本相當的高。
·?站在數據冷熱的角度看,數據分為熱數據和冷數據,熱數據通常是指需要頻繁操作的數據,反之為冷數據,例如對于視頻網站來說,視頻基本信息 基本上在各個業務線都是經常要操作的數據,而用戶的觀看記錄不一定是經 常需要訪問的數據,這里暫且不討論兩者數據規模的差異,單純站在數據冷 熱的角度上看,視頻信息屬于熱數據,用戶觀看記錄屬于冷數據。如果將這 些冷數據放在Redis中,基本上是對于內存的一種浪費,但是對于一些熱數據可以放在Redis中加速讀寫,也可以減輕后端存儲的負載,可以說是事半功倍
四、用好Redis的建議
①切勿當作黑盒使用,開發與運維同樣重要
·?很多使用Redis的開發者認為只要會用API開發相應的功能就可以,更有甚者認為Redis就是get、set、del,不需要知道Redis的原理。但是在我們實際運維和使用Redis的過程中發現,很多線上的故障和問題都是由于完全把 Redis當做黑盒造成的,如果不了解Redis的單線程模型,有些開發者會在有上千萬個鍵的Redis上執行keys*操作,如果不了解持久化的相關原理,會在 一個寫操作量很大的Redis上配置自動保存RDB。而且在很多公司內只有專職的關系型數據庫DBA,并沒有NoSQL的相關運維人員,也就是說開發者很有可能會自己運維Redis,對于Redis的開發者來說既是好事又是壞事。站在好的方面看,開發人員可以通過運維Redis真正了解Redis的一些原理,不 單純停留在開發上。站在壞的方面看,Redis的開發人員不僅要支持開發, 還要承擔運維的責任,而且由于運維經驗不足可能會造成線上故障。但是從實際經驗來看,運維足夠規模的Redis會對用好Redis更加有幫助
②閱讀源碼
·?前面提到過,Redis是開源項目,由于作者對Redis代碼的極致追 求,Redis的代碼量相對于許多NoSQL數據庫來說是非常小的,也就意味著 作為普通的開發和運維人員也是可以“吃透”Redis的。通過閱讀優秀的源碼,不僅能夠加深我們對于Redis的理解,而且還能提高自身的編碼水平, 甚至可以對Redis做定制化,也就是說可以修改Redis的源碼來滿足自身的需求,例如新浪微博在Redis的早期版本上做了很多的定制化來滿足自身的需求,豌豆莢也開源基于Proxy的Redis分布式實現Codis
五、歷史版本
·?Redis借鑒了Linux操作系統對于版本號的命名規則:
·?版本號第二位如果是奇數,則為非穩定版本(例如2.7、2.9、3.1)
·?版本號第二位如果是偶數,則為穩定版 本(例如2.6、2.8、3.0、3.2)
·?當前奇數版本就是下一個穩定版本的開發版本,例如2.9版本是3.0版本的開發版本
·?所以我們在生產環境通常選取偶數版本的Redis,如果對于某些新的特性想提前了解和使用,可以選擇最新的奇數版本
①Reids 2.6
·?Redis2.6在2012年正式發布,經歷了17個版本,到2.6.17版本,相比于 Redis2.4,主要特性如下:
·?服務端支持Lua腳本
·?去掉虛擬內存相關功能
·?放開對客戶端連接數的硬編碼限制
·?鍵的過期時間支持毫秒
·?從節點提供只讀功能
·?兩個新的位圖命令:bitcount和bitop
·?增強了redis-benchmark的功能:支持定制化的壓測,CSV輸出等功 能
·?基于浮點數自增命令:incrbyfloat和hincrbyfloat
·?redis-cli可以使用--eval參數實現Lua腳本執行
·?shutdown命令增強
·?info可以按照p輸出,并且添加了一些統計項
·?重構了大量的核心代碼,所有集群相關的代碼都去掉了,cluster功 能將會是3.0版本最大的亮點
·?sort命令優化
②Redis 2.8
·?Redis2.8在2013年11月22日正式發布,經歷了24個版本,到2.8.24版本, 相比于Redis2.6,主要特性如下:
·?添加部分主從復制的功能,在一定程度上降低了由于網絡問題,造 成頻繁全量復制生成RDB對系統造成的壓力
·?嘗試性地支持IPv6
·?可以通過config set命令設置maxclients
·?可以用bind命令綁定多個IP地址
·?Redis設置了明顯的進程名,方便使用ps命令查看系統進程
·?config rewrite命令可以將config set持久化到Redis配置文件中
·?發布訂閱添加了pubsub命令
·?Redis Sentinel第二版,相比于Redis2.6的Redis Sentinel,此版本已經 變成生產可用
③Redis 3.0
·?Redis3.0最大的改動就是添加Redis的分布式實現Redis Cluster,填補了Redis官方沒有分布式實現的空白。Redis Cluster經歷了4年才正式發布也是 有原因的,具體可以參考Redis Cluster的開發日志:http://antirez.com/news/79
·?Redis3.0在2015年4月1日正式發布, 相比于Redis2.8主要特性如下:
·?Redis Cluster:Redis的官方分布式實現
·?全新的embedded string對象編碼結果,優化小對象內存訪問,在特定 的工作負載下速度大幅提升
·?lru算法大幅提升
·?migrate連接緩存,大幅提升鍵遷移的速度。
·?migrate命令兩個新的參數copy和replace
·?新的client pause命令,在指定時間內停止處理客戶端請求
·?bitcount命令性能提升
·?config set設置maxmemory時候可以設置不同的單位(之前只能是字 節),例如config set maxmemory1gb
·?Redis日志小做調整:日志中會反應當前實例的角色(master或者 slave)
·?incr命令性能提升
④Redis 3.2
·?Redis3.2在2016年5月6日正式發布,相比于Redis3.0主要特征如下:
·?添加GEO相關功能
·?SDS在速度和節省空間上都做了優化
·?支持用upstart或者systemd管理Redis進程
·?新的List編碼類型:quicklist
·?從節點讀取過期數據保證一致性
·?添加了hstrlen命令
·?增強了debug命令,支持了更多的參數。
·?Lua腳本功能增強
·?添加了Lua Debugger
·?config set支持更多的配置參數
·?優化了Redis崩潰后的相關報告
·?新的RDB格式,但是仍然兼容舊的RDB
·?加速RDB的加載速度
·?spop命令支持個數參數
·?cluster nodes命令得到加速
·?Jemalloc更新到4.0.3版本
⑤Redis 4.0
·?可能出乎很多人的意料,Redis3.2之后的版本是4.0,而不是3.4、3.6、 3.8。一般這種重大版本號的升級也意味著軟件或者工具本身發生了重大變革
·?下面列出Redis4.0的新特性:
·?提供了模塊系統,方便第三方開發者拓展Redis的功能,更多模塊詳見:http://redismodules.com/
·?PSYNC2.0:優化了之前版本中,主從節點切換必然引起全量復制的 問題
·?提供了新的緩存剔除算法:LFU(Last Frequently Used),并對已有算法進行了優化
·?提供了非阻塞del和flushall/flushdb功能,有效解決刪除bigkey可能造 成的Redis阻塞
·?提供了RDB-AOF混合持久化格式,充分利用了AOF和RDB各自優 勢
·?提供memory命令,實現對內存更為全面的監控統計
·?提供了交互數據庫功能,實現Redis內部數據庫之間的數據置換
·?Redis Cluster兼容NAT和Docker
?