redis介紹
redis 是開源的餐屎,基于內存的數據存儲系統(tǒng),可以用作數據庫队丝、緩存和消息中間件靡馁。
redis支持多種數據存儲結構,包括string, hashes, lists, sets, sorted sets机久。
通過復制臭墨、持久化和數據分片等特性,可以很方便地將redis擴展成一個能夠包好數百GB膘盖、每秒處理上百萬次請求的系統(tǒng)胧弛。
持久化
對于基于內存存儲的數據庫,一個很重要的問題是侠畔,服務器關閉時结缚,數據的安全性問題。redis有兩種持久化方案软棺,保證了數據的安全性红竭。
RDB
RDB是一種按照指定時間周期定期保存redis數據鏡像到一個單文件中的持久化方式。
非常適用于用作容災備份喘落,因為RDB文件可以傳輸至不同地方備份茵宪,且服務器能夠很快地從RDB文件中恢復數據。
但是RDB方式不適用于對數據丟失方案容忍度很低的場景瘦棋,因為按周期備份數據鏡像眉厨,盡管周期可以設置得很短,但是仍然有丟失數據的風險兽狭。AOF
該方式能夠以AOF文件的方式憾股,保存每次對redis的數據修改。AOF文件是一個只允許追加的log文件箕慧,所以沒有查找?guī)淼男阅芟姆颉.斘募^大時,redis能夠自動重新AOF文件(合并部分同類操作INCR A 1, INCR A 1 --> INCR A 2).
redis的基本數據結構簡介
1. string
redis的string可以存儲以下三種類型的值:
- 字節(jié)串(byte string)
- 整數
- 浮點數
當執(zhí)行set key value命令時颠焦,redis檢測到value值可以轉化為整數或者浮點數斩熊,會更改其數據類型,使其支持對整數和浮點數的特殊操作伐庭,如自增和自減INCR, INCRBY
等操作粉渠,redis的強大之處還在于其支持對字符串的截取和二進制為操作。
命令 | 行為 |
---|---|
GET | 獲取存儲在給定間中的值 |
SET | 設置存儲在給定鍵中的值 |
DEL | 刪除 |
APPEND | 在指定鍵末尾追加 |
INCR | 增加1(對于int類型) |
2. list
Redis的列表允許用戶從序列的==兩端==推入或者彈出元素圾另、獲取元素霸株,執(zhí)行各種常見的列表操作,如獲取子列表集乔。
3. set
集合以==無序==的方式來存儲多個各不相同的元素去件,用戶可以快速地對集合執(zhí)行添加元素、移除元素以及檢查一個元素是否存在于集合里的操作。
并且可以對多個set進行差集尤溜、交集倔叼、并集計算。
4. hash
散列可以讓用戶將多個鍵值對存儲到一個Redis鍵里面宫莱。從功能上來說丈攒,Redis為散列值提供了一些和字符串值相同的特性,使得散列非常適用于將一些相關的數據存儲在一起授霸。我們可以把這種數據聚集看作是關系==數據庫中的行==肥印,或者==文檔存儲中的文檔==。
5. sort set
有序集合存儲著==成員與分值之間的映射==绝葡,并且提供了分值處理命令,以及根據分值大小有序地獲雀桂摹(fetch)或掃描(scan)成員和分值的命令藏畅。
6. 發(fā)布&訂閱
訂閱者(listener)訂閱頻道(channel),發(fā)送者(sender)想頻道發(fā)送二進制字符串消息功咒。每當有消息發(fā)送至指定頻道時愉阎,頻道的所有訂閱者都會收到消息。
命令 | 行為 |
---|---|
SUBSCRIBE | SUBSCRIBE channel [channel ...] ——訂閱給定的一個或多個頻道 |
UNSUBSCRIBE | UNSUBSCRIBE [channel [channel ...]]——退訂給定的一個或多個頻道力奋,如果未指定頻道榜旦,則退訂所以頻道 |
publis | PUBLISH channel message ——向給定頻道發(fā)送消息 |
PSUBSCRIBE | PSUBSCRIBE pattern [pattern ...] ——訂閱與給定模式想匹配的所有頻道 |
PUNSUBSCRIBE | PUNSUBSCRIBE [pattern ...]——退訂給定模式 |
事務
MULTI, EXEC, DISCARD & WATCH作為redis事務的基本命令,允許原子性地執(zhí)行一組redis操作景殷。
- 保證所有事務內的命令將會串行順序執(zhí)行溅呢,保證不會在事務的執(zhí)行過程中被其他客戶端打斷。不同于關系型數據庫的事務概念猿挚,redis保證會在執(zhí)行完畢上一個事務的所有命令后才會處理其他客戶端的命令咐旧。
- 事務內的命令全部執(zhí)行或一個都不執(zhí)行。
> MULTI
OK
> INCR foo
QUEUED
> INCR bar
QUEUED
> EXEC
1) (integer) 1
2) (integer) 1
-
事務運行中出錯
- 在執(zhí)行EXEC調用前出錯绩蜻,如語法錯誤铣墨、out of memmeroy錯誤。如果命令入隊是返回QUEUED办绝,則入隊成功伊约;否則入隊失敗,客戶端會停止并取消該事務孕蝉。
- 執(zhí)行EXEC調用后出錯屡律,如對string類型的鍵調用了list類型的操作。==對于此類錯誤降淮,redis并未進行特殊處理疹尾,即使事務中某些命令產生了此類錯誤,事務中的其他命令仍會繼續(xù)執(zhí)行下去。此特性有別于傳統(tǒng)關系型數據庫的事務概念纳本。== 簡而言之窍蓝,redis不支持事務回滾。
MULTI
+OK
SET a 3
abc
+QUEUED
LPOP a
+QUEUED
INCR a
EXEC
*3
+OK
-ERR Operation against a key holding the wrong kind of value
(integer) 4
為什么redis不支持事務回滾
redis命令只會因為語法錯誤而失敗繁成,在事務命令入隊時就能檢查到該錯誤吓笙;或者錯誤運用了鍵的命令。這就是說巾腕,失敗的命令是有編程錯誤造成的面睛,這些錯誤應該在開發(fā)過程中被發(fā)現(xiàn),不應該出現(xiàn)在生產環(huán)境中尊搬。
因此不需要支持回滾叁鉴,是redis內部保持了簡單和快速高效。
PS: 使用事務主要是為了:移除競爭條件佛寿。從事務的特性我們知道幌墓,redis的事務能夠保證事務內的所有命令在不被其他客戶端打斷的情況下順序執(zhí)行。
redis沒有實現(xiàn)傳統(tǒng)關系型數據庫的select ... for update的悲觀鎖
悲觀鎖加鎖會造成客戶端競爭條件的長時間等待冀泻,所以為了盡可能減少客戶端等待時間常侣,redis未實現(xiàn)for update的悲觀鎖機制。
而是通過watch命令弹渔,檢測某值是否被搶先修改胳施,并在發(fā)生時給客戶端返回錯誤。該機制類似于關系型數據庫中根據版本號實現(xiàn)的樂觀鎖機制肢专。
通過配置主從復制來提升redis的讀性能
redis復制
復制可以讓其他服務器擁有一個不斷更新的數據副本舞肆,擴展系統(tǒng)的讀請求處理能力。
從服務器連接住服務器時的步驟
步驟序列 | 主服務器操作 | 從服務器操作 |
---|---|---|
1 | 等待命令進入 | 連接主服務器博杖,發(fā)送SYNC同步命令 |
2 | 開始I執(zhí)行BGSAVE胆绊,備份數據副本,在此期間使用緩沖區(qū)記錄BGSAVE之后執(zhí)行的所以命令 | 根據配置選項決定是繼續(xù)使用現(xiàn)有數據(if has)來處理客戶端的命令請求欧募,還是想發(fā)送請求的客戶端返回錯誤 |
3 | BGSAVE執(zhí)行完畢压状,想從服務器發(fā)送快照文件,并在發(fā)送期間繼續(xù)使用緩沖區(qū)記錄被執(zhí)行的命令 | 丟棄所有舊數據(if has)跟继,開始載入主服務器發(fā)來的快照 |
4 | 快照文件發(fā)送完畢种冬,開始想從服務器發(fā)送存儲在緩沖區(qū)里面的寫命令 | 完成對快照文件的解釋,開始正常接受命令請求 |
5 | 緩沖區(qū)存儲的寫命令發(fā)送完畢舔糖,此后每執(zhí)行一個寫命令娱两,就行從服務器發(fā)送相同的寫命令 | 執(zhí)行主服務器發(fā)來的所有存儲在緩沖區(qū)的寫命令;此后金吗,接收并執(zhí)行主服務器傳來的每個寫命令 |
從服務器在進行同步是十兢,會清空自身原本數據趣竣。
redis不支持主主復制
當多個從服務器嘗試鏈接同一個主服務器的時候:
- 當上表步驟3尚未執(zhí)行時,所有服務器都會接受到相同的快照文件和相同的緩沖區(qū)寫命令
- 當步驟3正在執(zhí)行或者已經執(zhí)行完畢旱物,新連接的從服務器會重新執(zhí)行一遍步驟1-5
主從鏈
redis可以組成如下圖所示的主從鏈遥缕。
因為redis的復制會占用主服務器的網絡和其他開銷,如果一個主服務器需要同步太多的從服務器時宵呛,可能會造成主服務器不可用单匣,所以可以組成如下所示的主從鏈樹狀結構,用以在提升整體讀性能的前提下宝穗,減輕主服務器的同步開銷户秤。
redis集群
參考資料
https://redis.io/
http://redisdoc.com
《Redis實戰(zhàn)》