告訴你Redis是多麼牛

我不喜歡之前的標題,但是一篇介紹性的文章,讀一讀還不錯。先轉載一篇介紹的文章,有機會和大家一起討論下redis內部的結構和實現原理。

概述:

Redis 是一個 Key-Value 存儲系統。和 Memcached 類似,它支持存儲的 value 類型相對更多,包括 string(字符串)、 list(鏈表)、 set(集合)和 zset(有序集合)。這些數據類型都支持 push/pop、add/remove 及取交集並集和差集及更豐富的操作,而且這些操作都是原子性的。在此基礎上,Redis 支持各種不同方式的排序。與 memcached 一樣,爲了保證效率,數據都是緩存在內存中。區別的是 Redis 會週期性的把更新的數據寫入磁盤或者把修改操作寫入追加的記錄文件,並且在此基礎上實現了 master-slave(主從)同步。

Key-Value存儲系統

Key-Value Store 是當下比較流行的話題,尤其在構建諸如搜索引擎、IM、P2P、遊戲服務器、SNS 等大型互聯網應用以及提供雲計算服務的時候,怎樣保證系統在海量數據環境下的高性能、高可靠性、高擴展性、高可用性、低成本成爲所有系統架構們挖苦心思考慮的重點,而
怎樣解決數據庫服務器的性能瓶頸是最大的挑戰。
Key-Value Store 更加註重對海量數據存取的性能、分佈式、擴展性支持上,並不需要傳統關係數據庫的一些特徵,例如:Schema、事務、完整 SQL 查詢支持等等,因此在分佈式環境下的性能相對於傳統的關係數據庫有較大的提升。

爲什麼要選擇Key-Value Store

  1. 大規模互聯網應用
    一類是仍然採用RDBMS,然後通過對數據庫的垂直和水平切分將整個數據庫部署到一個集羣上,缺點在於它是針對特定應用,通用型不足
    另一類就是google採用的方法,拋棄RDBMS,採用Key-Value形式存儲,這樣可以極大增強系統的可擴展性。

  2. 雲存儲
    如果說上一個問題還有可以替代的解決方案(切割數據庫)的話,那麼對於雲存儲來說,也許 key-value 的 store 就是唯一的解決方案了。雲存儲簡單點說就是構建一個大型的存儲平臺給別人用,這也就意味着在這上面運行的應用其實是不可控的。如果其中某個客戶的應用隨着用戶的增長而不斷增長時,雲存儲供應商是沒有辦法通過數據庫的切割來達到 scale 的,因爲這個數據是客戶的,供應商不瞭解這個數據自然就沒法作出切割。在這種情況下,key-value 的 store 就是唯一的選擇了,因爲這種條件下的 scalability 必須是自動完成的,不能有人工干預。這也是爲什麼幾乎所有的現有的雲存儲都是 key-value 形式的,例如 Amazon的 smipleDB,底層實現就是 key-value,還有 google 的  GoogleAppEngine,採用的是 BigTable的存儲形式。


Key-Value Store 最大的特點就是它的可擴展性,這也就是它最大的優勢。所謂的可擴展性,
在我看來這裏包括了兩方面內容。一方面,是指 Key-Value Store 可以支持極大的數據的存儲,它的分佈式的架構決定了只要有更多的機器,就能夠保證存儲更多的數據。另一方面,是指它可以支持數量很多的併發的查詢。對於 RDBMS,一般幾百個併發的查詢就可以讓它很吃
力了,而一個 Key-Value Store,可以很輕鬆的支持上千的併發查詢。下面而簡單的羅列了一些特點:
  Key-value store:一個  key-value  數據存儲系統,只支持一些基本操作,如: SET(key, value) 和  GET(key)  等;
  分佈式:多臺機器(nodes)同時存儲數據和狀態,彼此交換消息來保持數據一致,可視爲一個完整的存儲系統。
  數據一致:所有機器上的數據都是同步更新的、不用擔心得到不一致的結果;
  冗餘:所有機器(nodes)保存相同的數據,整個系統的存儲能力取決於單臺機器(node)的能力;
  容錯:如果有少數  nodes  出錯,比如重啓、當機、斷網、網絡丟包等各種  fault/fail  都不影響整個系統的運行;
  高可靠性:容錯、冗餘等保證了數據庫系統的可靠性。

初識Redis

Redis是一個開源的使用ANSI C語言編寫,支持網絡、可基於內存且可持久化的日誌型、Key-Value數據庫,並且提供多個語言的API,訪問十分便捷。

Redis數據類型:

作爲 Key-value 型數據庫,Redis 也提供了鍵(Key)和鍵值(Value)的映射關係。但是,除
了常規的數值或字符串,Redis 的鍵值還可以是以下形式之一:
  Lists  (列表)
  Sets  (集合)
  Sorted sets  (有序集合)
  Hashes  (哈希表)
鍵值的數據類型決定了該鍵值支持的操作。Redis 支持諸如列表、集合或有序集合的交集、並集、查集等高級原子操作;同時,如果鍵值的類型是普通數字,Redis 則提供自增等原子操作。

Redis持久化:

通常,Redis 將數據存儲於內存中,或被配置爲使用虛擬內存。通過兩種方式可以實現數據持久化:使用截圖的方式,將內存中的數據不斷寫入磁盤;或使用類似 MySQL 的日誌方式,記錄每次更新的日誌。前者性能較高,但是可能會引起一定程度的數據丟失;後者相反。

Redis主從同步:

Redis支持將數據同步到多臺從庫,這種特性對提高讀取性能非常有益

Redis性能:

相比需要依賴磁盤記錄每個更新的數據庫,基於內存的特性無疑給Redis帶來了非常優秀的性能,讀寫操作之間有顯著的性能差異
性能測試結果:

SET操作每秒鐘 110000 次,GET操作每秒鐘 81000 次,服務器配置如下:
Linux 2.6, Xeon X3320 2.5Ghz.
stackoverflow 網站使用 Redis 做爲緩存服務器。

適用場合:

Redis其實開創了一種新的數據存儲思路,使用Redis,我們不用再面對功能單調的數據庫時,把精力放在如何把大象放進冰箱的問題,而是利用Redis提供的靈活多變的數據結構和數據操作,爲不同的大象構建不同的冰箱。

下面是一些Redis常用的場景:

1. 取最新N個數據的操作

比如典型的取你網站的最新文章,通過下面方式,我們可以將最新的 5000 條評論的 ID 放在Redis 的 List 集合中,並將超出集合部分從數據庫獲取。使用 LPUSH latest.comments<ID>命令,向 list 集合中插入數據插入完成後再用 LTRIM latest.comments 0 5000 命令使其永遠只保存最近 5000 個 ID如果你還有不同的篩選維度,比如某個分類的最新 N 條,那麼你可以再建一個按此分類的List,只存 ID 的話,Redis 是非常高效的。

2. 排行榜應用,取TOP N操作

這個需求與上面需求的不同之處在於,前面操作以時間爲權重,這個是以某一個條件爲權重,比如按購買的次數或者頂的次數,這時候就需要 sorted set 出馬,將你要排序的值設置爲sorted set的score,將具體的數據設置爲相應的value,每次只需要執行一條ZADD命令即可。

3. 需要精確設定過期時間的應用

比如你可以把上面說到的 sorted  set 的 score 值設置成過期時間的時間戳,那麼就可以簡單地通過過期時間排序,定時清除過期數據了,不僅是清除 Redis 中的過期數據,你完全可以把 Redis 裏這個過期時間當成是對數據庫中數據的索引,用 Redis 來找出哪些數據需要過期刪除,然後再精準地從數據庫中刪除相應的記錄。

4.計數器應用
Redis的命令是原子性的,你可以輕鬆利用INCR、DECR命令來構建計數器系統(底層的寫入是單線程模型,併發寫會按到位順序執行)

5.Uniq操作,獲取某段時間所有數據去重值

這個使用Redis的Set數據結構最合適,只需要不斷將數據往Set中扔就行,set就是集合,會自動去重

6.實時系統、發垃圾系統

通過上面說到的 set 功能,你可以知道一個終端用戶是否進行了某個操作,可以找到其操作的集合並進行分析統計對比等。沒有做不到,只有想不到。

7.Pub、Sub構建實時消息系統

Redis 的 Pub/Sub 系統可以構建實時的消息系統,比如很多用 Pub/Sub 構建的實時聊天系統的例子。

8. 構建隊列系統

使用list可以構建隊列系統,使用sorted set 甚至可以構建有優先級的隊列系統。

9. 緩存

性能優於Memcached,並且更優秀的在於數據結構更加多樣化

Redis作者的宣言

宣言中,作者列舉了Redis的7大原則,可以向大家闡明Redis的思想,看了之後我覺得Redis的作者的確牛叉,Redis這款產品這的是程序猿的福利:

  1. Redis 是一個操作數據結構的語言工具,它提供基於 TCP 的協議以操作豐富的數據結構。
    在 Redis 中,數據結構這個詞的意義不僅表示在某種數據結構上的操作,更包括了結構本身及這些操作的時間空間複雜度。

  2. Redis 定位於一個內存數據庫,正是由於內存的快速訪問特性,才使得 Redis 能夠有如此高的性能,才使得 Redis 能夠輕鬆處理大量複雜的數據結構,Redis 會嘗試其它的存儲方面的選擇,但是永遠不會改變它是一個內存數據庫的角色。

  3. Redis 使用基礎的 API 操作基礎的數據結構, Redis 的 API 與數據結構一樣,都是一些最基礎的元素,你幾乎可以將任何信息交互使用此 API 格式表示。作者調侃說,如果有其它非人類的智能生物存在,他們也能理解 Redis 的 API。因爲它是如此的基礎。(作者大大很有趣)

  4. Redis 有着詩一般優美的代碼,經常有一些不太瞭解 Redis  有的人會建議 Redis 採用一些其它人的代碼,以實現一些 Redis  未實現的功能,但這對我們來說就像是非要給《紅樓夢》接上後四十回一樣。
    5.Redis 始終避免複雜化,我們認爲設計一個系統的本質,就是與複雜化作戰。我們不會爲了一個小功能而往源碼裏添加上千行代碼,解決複雜問題的方法就是讓複雜問題永遠不要提複雜的問題。
    6.Redis 支持兩個層成的 API,第一個層面包含部分操作 API,但它支持用於分佈式環境下的 Redis。第二個層面的 API 支持更復雜的 multi-key 操作。它們各有所長,但是我們不會推出兩者都支持的 API,但我們希望能夠提供實例間數據遷移的命令,並執行 multi-key 操作。

  5. 我們以優化代碼爲樂,我們相信編碼是一件辛苦的工作,唯一對得起這辛苦的就是去享受它。如果我們在編碼中失去了樂趣,那最好的解決辦法就是停下來。我們決不會選擇讓Redis不好玩的開發模式。


我只能感嘆道:Redis乃神物,出污泥而不染,濯清漣而不妖

PS: Redis作者antirez曾笑稱Redis爲一個數據結構服務器,我認爲這個還是挺準確的,Redis的所有功能就是將數據以其固有的幾種結構來保存,並提供給用戶操作這幾種結構的接口。

redis:官方傳送門
redis中文:中文傳送門


原文出處:https://www.jianshu.com/p/01b37cdb3f33  作者:Monkey_D_lufy


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章