告訴你 Redis 是一個牛逼貨

humengyi發表於2018-09-11

概述:

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 操作。

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

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

PS: Redis作者antirez曾笑稱Redis為一個資料結構伺服器,我認為這個還是挺準確的,Redis的所有功能就是將資料以其固有的幾種結構來儲存,並提供給使用者操作這幾種結構的介面。

redis官方:

redis中文:

來自:Monkey_D_lufy

連結:

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31547542/viewspace-2213918/,如需轉載,請註明出處,否則將追究法律責任。

相關文章