Redis是一個開源的使用ANSI C語言編寫、支持網路、可基於記憶體亦可持久化的日誌型、Key-Value資料庫,並提供多種語言的API,其實當前最熱門的NoSQL資料庫之一,NoSQL還包括了Memcached和mongodb。關於Redis和Memcached的比較請點擊:Redis 和 Mem ...
Redis是一個開源的使用ANSI C語言編寫、支持網路、可基於記憶體亦可持久化的日誌型、Key-Value資料庫,並提供多種語言的API,其實當前最熱門的NoSQL資料庫之一,NoSQL還包括了Memcached和mongodb。關於Redis和Memcached的比較請點擊:Redis 和 Memcached 各有什麼優缺點。
Redis是NoSQL的一種,NoSQL(Not Only SQL),意即不僅僅是SQL,泛指非關係型的資料庫。隨著互聯網web2.0網站的興起,傳統的關係資料庫在應付web2.0網站,特別是超大規模和高併發的SNS類型的web2.0純動態網站已經顯得力不從心,暴露了很多難以剋服的問題,而非關係型的資料庫則由於其本身的特點得到了非常迅速的發展。NoSQL資料庫的產生就是為瞭解決大規模數據集合多重數據種類帶來的挑戰,尤其是大數據應用難題,包括超大規模數據的存儲。
1 Redis安裝
下載Redis的window安裝包,LZ下載的是3.0版本,解壓後如下圖所示:
點擊redis-server.exe啟動Redis服務,點擊redis-cli.exe啟動Redis客戶端。
2 Redis數據類型
2.1 keys
keys pattern 返回匹配模式的所有keys keys * : 查看該資料庫中所有的key type key 查看key類型 ttl key 返回key的剩餘過期時間,-1表示key不存在或者沒有設置過過期時間 exists key 測試key是否存在
del key1 key2 … keyN randomkey 返回當前資料庫隨機選擇的一個key,如資料庫是空的,則返回空串 persist key : 取消掉key的過期時間
exprie key seconds 為key設置過期時間,單位s。返回1成功,0表示key已設置過過期時間或者不存在
Redis預設有16個資料庫,序號分別是0-15,預設資料庫序號為0,以下命令是其相關命令。
dbsize 返回資料庫key數量 select db-index 選擇資料庫,redis預設16個,編號0-15 move key db-index 把key移到db-index資料庫下 rename oldkey newkey 原子重命名 renamenx oldkey newkey 同上,newkey存在則失敗 flushdb 刪除當前db的所有key flushall 刪除所有db的所有key ping 測試連接是否存活(返回PONG表示連接成功) echo xxx 在命令行列印xxx消息 info 返回redis伺服器信息 config get key 返回對應的配置信息,config get * 返回所有配置信息 clear 清屏操作
2.2 string類型
string 是 redis 最基本的類型,而且 string 類型是二進位安全的。意思是 redis 的 string 可以包含任何數據。比如 jpg 圖片或者序列化的對象。從內部實現來看其實 string 可以看作 byte 數組,最大上限是 1G 位元組。下麵是 string 類型的定義。
struct sdshdr { long len; long free; char buf[]; };
set key value 設置 key 對應的值為 string 類型的 value,返回 1 表示成功,0 失敗 setnx key value 同上,如果 key 已經存在,返回 0 。nx 是 not exist 的意思 get key 獲取 key 對應的 string 值,如果 key 不存在返回 nil getset key value 原子的設置 key 的值,並返回 key 的舊值。如果 key 不存在返回 nil mget key1 key2 ... keyN 一次獲取多個 key 的值,如果對應 key 不存在,則對應返回 nil。
mset key1 value1 ... keyN valueN 一次設置多個 key 的值,成功返回 1 表示所有的值都設置了,失敗 返回 0 表示沒有任何值被設置 msetnx key1 value1 ... keyN valueN 同上,但是不會覆蓋已經存在的 incr key 對 key 的值做加加操作,並返回新的值。註意 incr不是 int 的 value 會返回錯誤,incr 一 個不存在的 key,則設置 key 為 1 decr key 同上,但是做的是減減操作,decr 一個不存在 key,則設置 key 為-1 incrby key integer 同 incr,加指定值,key不存在時候會設置 key,並認為原來的value是 0 decrby key integer 同 decr,減指定值。decrby 完全是為了可讀性,我們完全可以通過 incrby 一個負 值來實現同樣效果,反之一樣。 append key value 給指定 key 的字元串值追加 value,返回新字元串值的長度。 substr key start end 返回截取過的 key 的字元串值,註意並不修改 key 的值,下標是從 0 開始的。
註意:substr的start和end區間是前閉後閉的。
2.3 list
list類型實質是一個每個元素都是string類型的雙向鏈表,所以push和pop命令的演算法時間複雜度都是O(1),另外list還會記錄鏈表的長度,所以llen操作也是O(1)。鏈表的最大長度是(2的32次方-1)。我們可以通過push,pop操作從鏈表的頭部或者尾部添加刪除元素。這使得list既可以用作棧,也可以用作隊列。有意思的是list的 pop 操作還有阻塞版本的。當我們[lr]pop一個list對象是,如果list是空,或者不存在,會立即返回nil。但是阻塞版本的b[lr]pop 可以則可以阻塞,當然可以加超時時間,超時後也會返回nil。
lpush key string 在 key 對應 list 的頭部添加字元串元素,返回 1 表示成功,0 表示 key 存在且不是 list類型 rpush key string 同上,在尾部添加 lpop key 從 list 的頭部刪除元素,並返回刪除元素。如果 key 對應 list 不存在或者是空返回 nil,如果 key 對應值不是 list 返回錯誤 rpop key 同上,但是從尾部刪除 llen key 返回 key 對應 list 的長度,key 不存在返回 0,如果 key 對應類型不是 list 返回錯誤 lrange key start end 返回指定區間內的元素,下標從 0 開始,負值表示從後面計算,-1 表示倒數第一個元素 ,key 不存在返回空列表 ltrim key start end 截取 list,保留指定區間內元素,成功返回 1,key 不存在返回錯誤
lset key index value 設置 list 中指定下標的元素值,成功返回 1,key 或者下標不存在返回錯誤 lrem key count value 從 key 對應 list 中刪除 count 個和 value 相同的元素。count 為 0 時候刪除全部 linsert key before value value2 在值value前插入值value2 linsert key after value value2 同上,不過是在value後插入值value2 blpop key1...keyN timeout 從左到右掃描返回對第一個非空 list 進行 lpop 操作並返回,比如 blpop list1 list2 list3 0 ,如果 list 不存在,list2,list3 都是非空則對 list2 做 lpop 並返回從 list2 中刪除的元素。如果所有的 list 都是空或不存在,則會阻塞 timeout 秒,timeout 為 0 表示一直阻塞。當阻塞時,如果有client 對 key1...keyN 中的任意 key 進行 push 操作,則第一在這個 key 上被阻塞的 client 會立即返回。如果超時發生,則返回 nil。有點像 unix 的 select 或者 poll。 brpop 同 blpop,一個是從頭部刪除一個是從尾部刪除。 rpoplpush srckey destkey 從 srckey 對應 list 的尾部移除元素並添加到 destkey 對應 list 的頭部,最後返回被移除的元素值,整個操作是原子的.如果 srckey 是空或者不存在返回 nil。
2.4 set
redis 的 set 是 string 類型的無序集合。 set 元素最大可以包含(2 的 32 次方-1)個元素。 set 的是通 過 hash table 實現的,所以添加,刪除,查找的複雜度都是 O(1)。 hash table 會隨著添加或者刪除自 動的調整大小。需要註意的是調整 hash table 大小時候需要同步(獲取寫鎖)會阻塞其他讀寫操作。
sadd key value 添加一個 string 元素到,key 對應的 set 集合中,成功返回 1,如果元素已經在集合中返回 0,key 對應的 set 不存在返回錯誤 srem key value 從 key 對應 set 中移除給定元素,成功返回 1,如果 value 在集合中不存在或者key 不存在返回 0,如果 key 對應的不是 set 類型的值返回錯誤 spop key 刪除並返回 key 對應 set 中隨機的一個元素,如果 set 是空或者 key 不存在返回 nil srandmember key 同 spop,隨機取 set 中的一個元素,但是不刪除元素 smove srckey dstkey value 從 srckey 對應 set 中移除 value 並添加到 dstkey 對應 set 中,整個操作是原子的。成功返回 1,如果 value 在 srckey 中不存在返回 0,如果 key 不是 set 類型返回錯誤 scard key 返回 set 的元素個數,如果 set 是空或者 key 不存在返回 0 sismember key value 判斷 value 是否在 set 中,存在返回 1, 0 表示不存在或者 key 不存在
smembers key 返回 key 對應 set 的所有元素,結果是無序的
sinter key1 key2...keyN 返回所有給定 key 的交集 sinterstore dstkey key1...keyN 同 sinter,但是會同時將交集存到 dstkey 下 sunion key1 key2...keyN 返回所有給定 key 的並集 sunionstore dstkey key1...keyN 同 sunion,並同時保存並集到 dstkey 下 sdiff key1 key2...keyN 返回所有給定 key 的差集 sdiffstore dstkey key1...keyN 同 sdiff,並同時保存差集到 dstkey 下
2.5 zset
和 set 一樣, sorted set 也是 string 類型元素的集合,不同的是每個元素都會關聯一個 double 類型 的 score ,元素順序有score決定。 sorted set 的實現是 skip list 和 hash table 的混合體。 當元素被添加到集合中時,一個元素到 score 的映射被添加到 hash table 中,所以給定一個元素獲取 score 的開銷是 O(1),另一個 score 到元素 的映射被添加到 skip list 並按照 score 排序,所以就可以有序的獲取集合中的元素。
zadd key score member 添加元素到集合,元素在集合中存在則更新對應 score,當該member已存在時,返回0,並更新該member的score值 zrem key member 刪除指定元素, 1 表示成功,如果元素不存在返回 0 zincrby key n member 增加對應 member 的 score 值,然後移動元素並保持 skip list 保持有序。返回更新後的 score 值 zrank key member 返回指定元素在集合中的排名(下標) ,集合中元素是按 score 從小到大排序的 zrevrank key member 同上,但是集合中元素是按 score 從大到小排序 zrange key start end 類似 lrange 操作從集合中去指定區間的元素。返回的是有序結果 zrevrange key start end 同上,返回結果是按 score 逆序的 zrangebyscore key min max 返回集合中 score 在給定區間的元素 zcount key min max 返回集合中 score 在給定區間的數量 zcard key 返回集合中元素個數 zscore key element 返回給定元素對應的 score zremrangebyrank key min max 刪除集合中排名在給定區間的元素 zremrangebyscore key min max 刪除集合中 score 在給定區間的元素
2.6 hash
redis hash 是一個 string 類型的 field 和 value 的映射表。它的添加,刪除操作都是 O(1) (平均).hash特別適合用於存儲對象。相較於將對象的每個欄位存成單個 string 類型。將一個對象存儲在 hash 類型中會占用更少的記憶體,並且可以更方便的存取整個對象。省記憶體的原因是新建一個 hash 對象時開始是用 zipmap(又稱為 small hash)來存儲的。這個 zipmap 其實並不是 hash table,但是 zipmap 相比正常的 hash 實現可以節省不少 hash 本身需要的一些元數據存儲開銷。儘管 zipmap 的添加,刪除,查找都是 O(n),但是由於一般對象的 field 數量都不太多。所以使用 zipmap 也是很快的,也就是說添加刪除平均還是 O(1)。如果 field 或者 value 的大小超出一定限制後, redis 會在內部自動將 zipmap替換成正常的 hash 實現. 這個限制可以在配置文件中指定。
hset key field value 設置 hash field 為指定值,如果 key 不存在,則先創建 hget key field 獲取指定的 hash field hmget key filed1....fieldN 獲取全部指定的 hash filed hmset key filed1 value1 ... filedN valueN 同時設置 hash 的多個 field hincrby key field integer 將指定的 hash filed 加上給定值 hexists key field 測試指定 field 是否存在 hdel key field 刪除指定的 hash field hlen key 返回指定 hash 的 field 數量 hkeys key 返回 hash 的所有 field hvals key 返回 hash 的所有 value hgetall key 返回 hash 的所有 filed 和 value
3 Redis高級特性
3.1 安全性
預設登錄Redis密碼,需要時可以自定義,設置密碼時最好設置一個比較複雜的密碼,防止暴力破解。因為redis執行速度非常快,正常配置下1s內可以進行150k次密碼登錄嘗試。
打開redis.window.conf配置文件,加上requirepass luoxn28配置如下:
配置完成後,啟動redis服務,註意,此時不要點擊redis-server.exe啟動,因此redis-server.exe啟動使用的是預設配置,可以在cmd命令行下啟動:
redis啟動後,輸入命令會提示沒有認證許可權,使用auth password即可:
3.2 主從複製
Redis主從複製配合和使用比較簡單,通過主從複製可以允許多個slave server擁有和master server相同的資料庫副本。
master可以擁有多個salve server,多個slave可以連接同一個master外,還可以連接到其他slave。主從複製不會阻塞master,同步數據時,master可以繼續處理client,提高系統伸縮性。
Redis主從複製過程:
- Salve與master建立連接,發送sync同步命令。
- Master會啟動一個後臺進程,將資料庫快照保存到文件中,同時master主進程會開始收集新的寫命令緩存。
- 後臺完成保存後,就將此文件發送給slave。
- slave將此文件保存到硬碟上。
Redis環境說明:
window下Redis服務作為master主機,window的IP為192.168.1.100,虛擬機下linux下的Redis作為slave,linux的IP為192.168.1.150。
在redis從機(linux環境)的redis.conf配置文件中加入以下配置:
主機寫入2條記錄到資料庫,然後從從機中讀取,註意:總計無法更新值,只能讀取。
master主機 slave從機
3.3 事務處理
Redis對事務的支持還比較簡單,redis只能保證一個client發起的事務中的命令可以連續執行,而中間不會插入其他client的命令。當一個client在一個連接中發出multi命令時,這個連接會進入一個事務的上下文,連接後續命令不會立即執行,而是先放到一個隊列中,當執行exec命令時,redis會順序的執行隊列中的所有命令。
在事務處理中使用discard可以取消事務的處理。redis在事務中如果發生錯誤時事務退出,但是在該錯誤之前的操作無法回滾。
3.4 持久化
redis是一個支持持久化的記憶體資料庫。snapshotting快照方式,預設的存儲方式,預設寫入dump.rdb的二進位文件中,可以配置redis在n秒內如果超過m個key被修改過就自動做快照append-only file aof方式,使用aof時候redis會將每一次的函 數都追加到文件中,當redis重啟時會重新執行文件中的保存的寫命令在記憶體中。
3.5 發佈訂閱消息
發佈訂閱(pub/sub)是一種消息通知模式,主要的目的是截除消息發佈者和消息訂閱者之間的耦合,Redis作為一個pub/sub的server,在訂閱者和發佈者之間起到了消息路由的功能。訂閱者可以通過subscribe和psubscribe命令向redis server訂閱自己感興趣的消息類型,redis將消息類型稱為通道(channel)。當發佈者通過publish命令向redis server發送特定類型的信息時,訂閱該信息類型的全部client都會收到此消息。
第一個redis客戶端訂閱changnel1,第二個redis客戶端訂閱channel1和channel2,第三個redis客戶端負責產生channel1和channel2消息,然後觀察第一個和第二個redis客戶端是否收到了訂閱消息。
3.6 虛擬記憶體
Redis的虛擬記憶體與操作系統的虛擬記憶體不是一回事,但是思路和目的都是相同的。就是暫時把不經常訪問的數據從記憶體交換到磁碟中,從而騰出寶貴的記憶體空間用於其他需要訪問的數據。尤其是對於redis這樣的記憶體資料庫,記憶體總是不夠用的。除了可以將數據分割到多個redis server外。另外能夠提高資料庫容量的辦法就是使用虛擬記憶體把那些不經常訪問的數據交換到磁碟上。
如果想啟用虛擬記憶體功能,在配置文件redis.conf中增加配置如下:
參考:
1、《Redis新手入門詳解》
2、Redis的高級應用之事務處理、持久化操作、pub_sub、虛擬記憶體