Redis
是 開源,內存 中的數據結構存儲系統,它能夠用做數據庫、緩存和消息中間件。它支持多種類型的數據結構,如 字符串strings
, 散列 hashes
, 列表 lists
, 集合 sets
, 有序集合 sorted sets
與範圍查詢, bitmaps, hyperloglogs 和 地理空間(geospatial) 索引半徑查詢。redis
Redis
還內置了 複製(replication
),LUA腳本(Lua scripting
), LRU驅動事件(LRU eviction
),事務(transactions
) 和不一樣級別的 磁盤持久化(persistence
), 並經過 Redis哨兵(Sentinel
)和自動 分區(Cluster
)提供高可用性(high availability
)。數據庫
嗯,沒錯這就是 redis
中文官方網站上面的介紹,簡潔明瞭。編程
咱們知道 redis
是一種非關係型數據庫 NoSQL
。而爲何出現 NoSQL
?NoSQL
又是什麼呢?數組
在一個網站訪問量不大的時候,咱們使用一個數據庫就足以應對流量請求。 緩存
隨着訪問量的上升,一個數據庫已經不能知足咱們的需求了。爲了更高的性能,咱們在中間加上了一個緩存層而且將數據庫作了集羣、結構優化和讀寫分離。服務器
而這裏的緩存就是 NoSQL
,固然作緩存也只是 NoSQL
的一種功能,就像 Redis
並不只僅有緩存這一種功能。好比它還能實現 簡單的消息隊列,解決Session共享,計數器,排行榜,好友關係處理 等等功能,可見 Redis
是一個很是強大工具,讓咱們來學習它吧!網絡
首先咱們拋開數據類型來說關於 Redis
的通用命令。數據結構
Redis
是一種 key
value
存儲的緩存數據庫,全部的數據都有一個本身惟一的key。app
這裏爲了方便演示,我使用了字符串相關的設置命令 編程語言
keys [pattern]
獲取符合要求的全部key。時間複雜度爲 O(n)
,通常在生產環境中不使用,由於 Redis
是單線程的,執行耗時的任務會阻塞其餘任務。通常會使用 scan
命令替代(非阻塞)。dbsize
獲取當前存儲數據個數。exists key
判斷是否存在該keydel key
刪除指定數據type key
獲取指定key的數據類型rename key newkey
重命名Redis
中不少數據都是用來做爲緩存數據的,而做爲緩存就須要有過時時間,在 Redis
中提供了很強大的過時時間設置功能。
expire key seconds
爲某個 key 設置過時時間。ttl key
查看某個 key 的剩餘時間,返回正數表明剩餘的時間,-1表明永久,-2表明已過時或不存在。在上面我說到了不少 Redis
做爲緩存能實現的其餘功能,好比計數器,排行榜,好友關係等,這些實現的依據就是靠着 Redis
的數據結構。在整個 Redis
中一共有五種基本的數據結構(還有些高級數據結構之後會講),他們分別是 字符串strings
, 散列 hashes
, 列表 lists
, 集合 sets
, 有序集合 sorted sets
。
在絕大部分編程語言中都有 String
字符串類型,對於做爲數據庫的 Redis
也是必不可少的。
set key value
設置值get key
獲取某個key的值mset key1 value1 key2 value2
批量設置而且是原子的,能夠用來減小網絡時間消耗mget key1 key2
批量獲取而且是原子的,能夠用來減小網絡時間消耗
incr key
自增指定key的值decr key
自減指定key的值incrby key value
自增指定數值decrby key value
自減指定數值incrbyfloat key floatvalue
增長指定浮點數 前面幾個操做就能夠用來實現計數器的功能。
setnx key value
若是不存在該key則能夠設置成功,不然會失敗,加上過時時間限制,則是redis實現分佈式鎖的一種方式(後面會提到)。set key value xx
與前面相反,若是存在則設置成功,不然失敗(至關於更新操做)
getset key newvalue
設置新值並返回舊值append key value
爲本來內容追加內容strlen key
獲取字符串長度getrange key start end
獲取指定範圍的內容setrange key index value
設置指定範圍的內容
setex key seconds value
設置值且設置過時時間set key value ex seconds nx
爲不存在的key設置值且設置過時時間,分佈式鎖的實現方式。
其實咱們能夠理解 hash
爲 小型Redis ,Redis
在底層實現上和 Java
中的 HashMap
差很少,都是使用 數組 + 鏈表 的二維結構實現的。
不一樣的是,在 Redis
中字典的值只能是字符串,並且他們 rehash
的方式不同,在 Redis
中使用的是 漸進式rehash 。
在 rehash 的時候會保留新舊兩個 hash 字典,在數據遷移的時候會將舊字典中的內容一點一點遷移到新字典中,查詢的同時會查詢兩個 hash 字典,等數據所有遷移完成纔會將新字典代替就字典。
下面咱們來看一下關於 hash
的基本操做。
hset key field value
設置字典中某個key的值hsetnx key field value
設置字典中某個key的值(不存在的)hmset key field1 value1 field2 value2 ...
批量設置hget key field
獲取字典中某個key的值hmget key field1 field2
批量獲取hgetall key
獲取所有
hdel key field
刪除某個keyhexists key field
判斷是否存在hlen key
獲取指定key對應的字典中的存儲個數hvals key
返回全部的valuehkeys key
返回全部的key
hincrby key field increValue
增長某個value的值(也能夠增長負數)hincrbyfloat key field floatValue
增長某個value的值(浮點數)
Redis
中的列表至關於 Java
中的 LinkedList
(雙向鏈表) ,也就是底層是經過 鏈表 來實現的,因此對於 list
來講 插入刪除操做很快,但 索引定位很是慢。
Redis
提供了許多對於 list
的操做,如出,入等操做,你能夠充分利用它們來實現一個 棧 或者 隊列。
下面咱們來看一下關於 list
的基本操做。
lpush key item1 item2 item3...
從左入棧rpush key item1 item2 item3...
從右入棧lpop key
從左出棧rpop key
從右出棧lindex key index
獲取指定索引的元素 O(n)謹慎使用lrange key start end
獲取指定範圍的元素 O(n)謹慎使用
linsert key before|after item newitem
在指定元素的前面或者後面添加新元素lrem key count value
刪除指定個數值爲value的元素
ltrim key start end
保留指定範圍的元素lset key index newValue
更新某個索引的值
blpop key timeout
沒有則阻塞(timeout指定阻塞時間 爲0表明永久)brpop key timeout
沒有則阻塞(timeout指定阻塞時間 爲0表明永久) 這兩個能夠用來實現消費者生產者
總結來講咱們可使用 左入又出或者右入左出 來實現隊列,左入左出或者右入右出 來實現棧。
Redis
中的 set
至關於 Java
中的 HashSet
(無序集合),其中裏面的元素不能夠重複,咱們能夠利用它實現一些去重的功能。咱們還有對幾個集合進行取交集,取並集等操做,這些操做就能夠獲取不一樣用戶之間的共同好友,共同愛好等等。
下面咱們就來看一下關於 set
的一些基本操做。
sadd key value
添加元素sdel key value
刪除某個元素sismember key value
判斷是不是集合中的元素srandmember key count
隨機獲取指定個數的元素(不會影響集合結構)spop key count
從集合中隨機彈出元素(會破壞結合結構)smembers key
獲取集合全部元素 O(n)複雜度scard key
獲取集合個數
sinter set1 set2 ...
獲取全部集合中的交集sdiff set1 set2 ...
獲取全部集合中的差集sunion set1 set2 ...
獲取全部集合中的並集
Redis
中的 zset
是一個 有序集合,經過它能夠實現不少有意思的功能,好比學生成績排行榜,視頻播放量排行榜等等。
zset
中是使用 跳錶 來實現的,咱們知道只有數組這種連續的空間才能使用二分查找進行快速的定位,而鏈表是不能夠的。跳錶幫助鏈表查找的時候節省了不少時間(使用跳的方式來遍歷索引來進行有序插入),若是不瞭解跳錶的同窗能夠補習一下。
下面咱們來看一下關於 zset
的一些基本操做。
zadd key score element
添加,score用於排序,value須要惟一,因爲使用的跳錶,時間複雜度爲 O(logn)。zrem key element
刪除某元素 O(1)時間複雜度zscore key element
獲取某個元素的分數zincrby key incrScore element
增長某個元素的分數zrange key start end [withscores]
獲取指定索引範圍的元素 加上withscores
則返回分數 O(logn + m)時間複雜度zrangebyscore key minScore maxScore [withscores]
獲取指定分數範圍的元素 加上withscores
則返回分數,O(logn + m)時間複雜度zcard key
獲取有序集合長度
在某些場景下咱們在一次操做中可能須要執行多個命令,而若是咱們只是一個命令一個命令去執行則會浪費不少網絡消耗時間,若是將命令一次性傳輸到 Redis
中去再執行,則會減小不少開銷時間。 可是須要注意的是 pipeline
中的命令並非原子性執行的,也就是說管道中的命令到達 Redis
服務器的時候可能會被其餘的命令穿插。
關係型數據庫具備 ACID
特性,Redis
能保證A(原子性)和I(隔離性),D(持久性)看是否有配置 RDB
或者 AOF
持久化操做,但沒法保證一致性,由於 Redis
事務不支持回滾。
咱們能夠簡單理解爲 Redis
中的事務只是比 Pipeline
多了個原子性操做,也就是不會被其餘命令給分割,如上圖。
multi
事務開始的標誌
exec
事務執行
discard
清除在這個事務中放入隊列的全部命令,即解除整個事務。
watch key
在事務開始前監控某個元素,若是在提交事務的時候發現這個元素的值被其餘客戶端更改了則事務會運行失敗。
unwatch key
解除監控
好了,這就是這篇文章所有的內容了,對於 Redis
你還有多少遺忘的或者沒學習到的呢?
若是文章對你有幫助的話,請給我點個贊哦(#^.^#)
關於 Redis
的文章接下來還會再寫,若是感興趣能夠關注我(#^.^#)。