一文入門Redis
一、Redis簡介
Redis:REmote DIctionary Server(遠程字典服務)。是一款使用C語言編寫的、開源的、基於內存的、高性能的、可持久化的非關系型Key-Value數據庫。
二、常用數據類型
1、String(字符串)
string是redis最基本的數據類型,一個key對應一個value。string類型是二進制安全的,可以包含任何數據,包括圖片、序列化的對象等,最大存儲512MB。
常用命令:
命令 | 描述 | 用法 |
---|---|---|
SET | 1、將value關聯到key;2、key已關聯則覆蓋;3、原本key帶有TTL(生存時間),那么TTL被清楚 | SET key value |
GET | 1、返回key所關聯的字符串值;2、key不存在返回null; | GET key |
SETEX | 1、將value關聯到key;2、設置key生存時間為seconds,單位為秒;3、如果key已關聯則覆蓋;4、原子操作,關聯與設置生存時間同時完成 | SETEX key seconds value |
SETNX | 1、將value關聯到key,當且僅當key不存在;2、若key已存在,不做任何動作 | SETNX key value |
2、Hash(哈希)
hash是一個string類型的field和value的映射表,key 還是key,但是value是多個鍵值對(key-value),比較適合存儲對象。
常用命令:
命令 | 描述 | 用法 |
---|---|---|
HSET | 1、將key中的field值設為value;2、filed已存在,被覆蓋 | HSET key field value |
HGET | 1、返回key中給定域field中的值 | HGET key field |
HDEL | 1、刪除key中的一個或多個指定域;2、不存在的域被忽略 | HDEL key field |
HEXISTS | 1、查看key中,給定域field是否存在,存在返回1,否,返回0 | HEXISTS key field |
HGETALL | 1、返回key中所有的域和值 | HGETALL key |
HLEN | 1、返回key中域的數量 | HLNE key |
3、List(列表)
list 列表,它是簡單的字符串列表,按照插入順序排序,你可以添加一個元素到列表的頭部(左邊)或者尾部(右邊),它的底層實際上是個鏈表。有序、可以重復。
常用命令:
命令 | 描述 | 用法 |
---|---|---|
LPUSH | 1、將一個或多個值value按順序插入到key的表頭;2、key不存在,則創建並插入;3、key存在但不是list類型,返回錯誤; | LPSUH key value |
LPUSHX | 1、將value插入到key的頭部,當且僅當key存在且為list類型;2、key不存在,什么都不做; | LPUSHX key value |
LPOP | 1、移除並返回key的頭元素; | LPOP key |
LRANGE | 1、返回key中指定區間的元素;2、可使用負數下標,-1表示list最后一個元素;3、start大於list最大下標,返回空列表;4、stop大於list最大下標,stop=list最大下標; | LRANG key start stop |
LSET | 1、將key下標為index的元素值設為value;2、index超出范圍或list為空,返回錯誤; | LSET key index value |
LINDEX | 1、返回key中,下標為index的元素; | LINDEX key index |
LLEN | 1、返回key的長度;2、key不存在,返回0; | LLEN key |
RPUSH | 1、將一個或多個值value按順序插入到key的表尾; | RPUSH key value |
RPUSHX | 1、將value插入到key的尾部,當且僅當key存在且為list類型; | RPUSHX key value |
RPOP | 1、移除並返回key的尾元素; | RPOP key |
4、Set(集合)
set 是 string 類型的無序集合。無序、不可重復
常用命令:
命令 | 描述 | 用法 |
---|---|---|
SADD | 1、將一個或多個元素加入key中,已存在的元素將返回0;2、key不存在,則創建並添加;3、key不是集合類型時,返回錯誤 | SADD key member |
SCARD | 1、返回key中對應的集合中的元素數量 | SCARD key |
5、Zset(有序集合)
Redis 有序集合和集合一樣也是 string 類型元素的集合,且不允許重復的成員。
不同的是每個元素都會關聯一個 double 類型的分數。redis 正是通過分數來為集合中的成員進行從小到大的排序。
有序集合的成員是唯一的,但分數(score)卻可以重復。
命令 | 描述 | 用法 |
---|---|---|
ZADD | 1、將一個或多個元素及其score值加入key中;2、如果已存在元素,則更新score值並重新插入; | ZADD key score member |
ZCARD | 1、返回key中元素個數 | ZCARD key |
ZRANGE | 1、返回key中指定區間類的成員,按score從小到大排序;2、相同score值按字典序排序;3、從大到小排序,使用ZREVRANGE命令;4、可通過WITHSCORES選項讓成員和它的score值一並返回 | ZRANGE key start stop [WITHSCORES] |
ZRANK | 1、返回有序集中成員member的排名,按score從小到大排序;2、排名以0為底,score最小的排名0 | ZRANK key member |
三、持久化
Redis 是一個內存數據庫將數據庫中的內容保存在內存中,這與傳統的MySQL等關系型數據庫直接將內容保存到硬盤中相比,內存數據庫的讀寫效率比傳統數據庫要快的多(內存的讀寫效率遠遠大於硬盤的讀寫效率),這也是Redis如此之快的原因。但是保存在內存中也隨之帶來了一個缺點,一旦斷電或者宕機,那么內存數據庫中的數據將會全部丟失。
為了解決這個缺點,Redis提供了將內存數據持久化到硬盤,以及用持久化文件來恢復數據庫數據的功能。Redis 支持兩種形式的持久化,分別是RDB(Redis DataBase)和AOF(Append Only File)。
1、持久化流程
- 客戶端向服務端發送寫操作(數據在客戶端的內存中)。
- 數據庫服務端接收到寫請求的數據(數據在服務端的內存中)。
- 服務端調用write這個系統調用,將數據往磁盤上寫(數據在系統內存的緩沖區中)。
- 操作系統將緩沖區中的數據轉移到磁盤控制器上(數據在磁盤緩存中)。
- 磁盤控制器將數據寫到磁盤的物理介質中(數據真正落到磁盤上)。
這5個過程是在理想條件下一個正常的保存流程,但是在大多數情況下,我們的機器等等都會有各種各樣的故障,這里划分了兩種情況:
- Redis數據庫發生故障,只要在上面的第三步執行完畢,那么就可以持久化保存,剩下的兩步由操作系統替我們完成。
- 操作系統發生故障,必須上面5步都完成才可以。
2、RDB
RDB持久化是指在指定的時間間隔內將內存中的數據集快照寫入磁盤。即將內存中數據以快照的方式寫入到二進制文件中,默認的文件名為dump.rdb。
將備份文件 (dump.rdb) 移動到 redis 安裝目錄並啟動服務即可回復數據,redis就會自動加載文件數據至內存了。Redis 服務器在載入 RDB 文件期間,會一直處於阻塞狀態,直到載入工作完成為止。
2.1、原理
把當前內存中的數據集快照寫入磁盤,也就是 Snapshot 快照(數據庫中所有鍵值對數據)。恢復時是將快照文件直接讀到內存里。也是Redis默認的持久化方式。
2.2、觸發方式
1、save
該命令會阻塞當前Redis服務器,執行save命令期間,Redis不能處理其他命令,直到RDB過程完成為止。執行完成時候如果存在老的RDB文件,就把新的替代掉舊的。我們的客戶端可能都是幾萬或者是幾十萬,這種方式顯然不可取。
“save m n”:表示m秒內數據集存在n次修改時,自動觸發bgsave。
redis.conf中默認配置:
save 900 1:表示900 秒內如果至少有 1 個 key 的值變化,則保存
save 300 10:表示300 秒內如果至少有 10 個 key 的值變化,則保存
save 60 10000:表示60 秒內如果至少有 10000 個 key 的值變化,則保存
2、bgsave
執行該命令時,Redis會在后台異步進行快照操作,快照同時還可以響應客戶端請求。
具體操作是Redis進程執行fork操作創建子進程,RDB持久化過程由子進程負責,完成后自動結束。阻塞只發生在fork階段,一般時間很短。基本上 Redis 內部所有的RDB操作都是采用 bgsave 命令。
2.3、優缺點
-
優點
1.RDB是一個非常緊湊(compact)的文件,它保存了redis 在某個時間點上的數據集。這種文件非常適合用於進行備份和災難恢復。
2.生成RDB文件的時候,redis主進程會fork()一個子進程來處理所有保存工作,主進程不需要進行任何磁盤IO操作。
3.RDB 在恢復大數據集時的速度比 AOF 的恢復速度要快。
-
缺點
1.RDB方式數據沒辦法做到實時持久化/秒級持久化。因為bgsave每次運行都要執行fork操作創建子進程,屬於重量級操作,如果不采用壓縮算法(內存中的數據被克隆了一份,大致2倍的膨脹性需要考慮),頻繁執行成本過高(影響性能)
2.RDB文件使用特定二進制格式保存,Redis版本演進過程中有多個格式的RDB版本,存在老版本Redis服務無法兼容新版RDB格式的問題(版本不兼容)
3.在一定間隔時間做一次備份,所以如果redis意外down掉的話,就會丟失最后一次快照后的所有修改(數據有丟失)
3、AOF
全量備份總是耗時的,AOF是一種更加高效的方式,工作機制很簡單,redis會將每一個收到的寫命令都通過write函數追加到文件中。通俗的理解就是日志記錄。
3.1、原理
通過保存Redis服務器所執行的寫命令來記錄數據庫狀態。
比如對於如下命令
set str1 "123"
sadd str2 "1" "2" "3"
lpush str3 "1" "2" "3"
RDB 持久化方式就是將 str1,str2,str3 這三個鍵值對保存到 RDB文件中,而 AOF 持久化則是將執行的 set,sadd,lpush 三個命令保存到 AOF 文件中。
3.2、配置
在redis.conf中,
- appendonly:默認值no,也就是說redis 默認使用的是rdb方式持久化,如果想要開啟 AOF 持久化方式,需要將 appendonly 修改為 yes。
- appendfilename :aof文件名,默認是"appendonly.aof"
- appendfsync:aof持久化策略的配置:
- no表示不執行fsync,由操作系統保證數據同步到磁盤,速度最快,但是不太安全;
- always表示每次寫入都執行fsync,以保證數據同步到磁盤,效率很低;
- everysec表示每秒執行一次fsync,可能會導致丟失這1s數據。通常選擇 everysec ,兼顧安全性和效率。
3.2、優缺點
-
優點
1.AOF可以更好的保護數據不丟失,一般AOF會每隔1秒,通過一個后台線程執行一次fsync操作,最多丟失1秒鍾的數據。
2.AOF日志文件的命令通過非常可讀的方式進行記錄,這個特性非常適合做災難性的誤刪除的緊急恢復。例如,如果我們不小心錯用了 FLUSHALL 命令,在重寫還沒進行時,我們可以手工將最后的 FLUSHALL 命令去掉,然后再使用 AOF 來恢復數據。
-
缺點
1.對於具有相同數據的的 Redis,AOF 文件通常會比 RDF 文件體積更大。(當AOF文件的大小超過所設定的閾值時,Redis就會啟動AOF文件的內容壓縮,只保留可以恢復數據的最小指令集)
2.RDB 使用快照的形式來持久化整個 Redis 數據,而 AOF 只是將每次執行的命令追加到 AOF 文件中,因此從理論上說,RDB 比 AOF 方式更健壯。官方文檔也指出,AOF 的確也存在一些 BUG,這些 BUG 在 RDB 沒有存在。
4、如何選擇持久化方式?
如果可以忍受一小段時間內數據的丟失,毫無疑問使用 RDB 是最好的,定時生成 RDB 快照(snapshot)非常便於進行數據庫備份, 並且 RDB 恢復數據集的速度也要比 AOF 恢復的速度要快,而且使用 RDB 還可以避免 AOF 一些隱藏的 bug;否則就使用 AOF 重寫。但是一般情況下建議不要單獨使用某一種持久化機制,而是應該兩種一起用,在這種情況下,當redis重啟的時候會優先載入AOF文件來恢復原始的數據,因為在通常情況下AOF文件保存的數據集要比RDB文件保存的數據集要完整。Redis后期官方可能都有將兩種持久化方式整合為一種持久化模型。
如果有學到東西,請點贊給予鼓勵,謝謝。