2.1.1全局命令
Key * 查看所有鍵,(慎用,會把所有鍵都遍歷一次并列出)
Dbsize 查看鍵總數,不會遍歷所有鍵,只是從內置函數中讀取一個數
Exists [key] 檢查鍵是否存在
Del [key] 刪除鍵
Expire [key] [seconds] 設置鍵過期時間
Type [key] 鍵的數據結構類型
2.1.2數據結構和內部編碼
Type命令實際返回的就是當前鍵的數據結構類型:string字符串,hash哈希,list列表,set集合,zset有序集合,但這些只是redis對外的數據結構,
?
?
實際上每種數據結構都有自己底層的內部編碼實現,而且試多種實現,這樣redis會在合適的場景選擇合適的內部編碼
String raw,int,embstr
Hash hashtable,ziplist
Key List linkedlist,ziplist
Set hashtable,intset
Zset skiplist,ziplist
可以通過object encoding命令查詢內部編碼。這樣的設計可以適應不同業務場景
2.1.3單線程架構
Redis使用了單線程架構和I/O多路復用模型來實現高性能的內存數據庫服務。
客戶端與服務端的模型可以簡化為:發送命令,執行命令,返回結果三步。
其中第二步因為redis是單線程來處理命令的,所以一條命令從客戶端到達服務端不會立刻被執行,所有命令都會進入一個隊列中,然后逐個被執行。這樣可以避免并發的問題。
為什么單線程還能這么快?
第一,純內存訪問,redis將所有數據放在內存中,內存的響應時長大約在100納秒,這是redis達到每秒萬級別訪問的重要基礎。
第二,非阻塞I/O,Redis使用epoll作為io多路復用技術的實現,再加上redis自身的事件處理模型將epoll中的連接,讀寫,關閉都轉換為事件,不在網絡io上浪費過多的時間
單線程避免了線程切換和竟態產生的消耗。
2.2字符串
是最基礎的數據類型,其它幾種數據類型也是在字符串的基礎上構建的;實際上字符串類型的值還可以是:字符串,數字,二進制,但值不能超過512MB
2.2.1命令
設置值
Set key value [ex seconds] [px milliseconds] [nx|xx]
Ex seconds:設置秒級過期時間
px milliseconds:設置毫秒級過期時間
Nx 鍵必須不存在,才可以設置成功,用于添加
Xx:與nx相反,鍵必須存在,才可以設置成功,用于更新
獲取值
Get key
批量設置值:
Mset key value [key value key value]
批量獲取
Mget key [key key key]
計數
Incr key
命令用于對值進行自增操作,返回結果又3種:
?
值不是整數,返回錯誤
值是整數,返回自增后結果
鍵不存在,按照值為0自增,返回結果為1
?
相關的還提供了decr自減,incrby自增指定數字,decrby自減指定數字,incrbyfloat自增浮點型
追加命令
Append key value
向value的尾部追加值
字符串長度:
strlen key
設置并返回原值
Getset key value
設置指定位置的字符
Setrange key offeset value
獲取部分字符串
Getrange key start end
2.2.2內部編碼
字符串類型有三種內部編碼:
Int:8個字節的長整形
Embstr:小于等于39個字節的字符串
Raw:大于39個字節的字符串
Redis會根據當前值的類型和長度決定使用那種內部編碼
2.2.3使用場景
緩存功能;
使用redis作為系統的緩存層關系型數據庫作為數據層。Reids具有支撐高并發的特性,所以緩存通常能起到加速讀寫和降低后端壓力的作用。
?
UserInfo getUserInfo(long id){
1,檢查redis種是否存在用戶信息
2,從redis種獲取session信息
3,如果沒有則序列化到redis
}
?
計數
許多應用都會使用redis實現計數功能
共享session
一個分布式web服務將用戶的session信息保存再各個服務器中,這會造成一個問題:出于負載均衡的考慮,分布式服務會將用戶的訪問均衡到不同的服務器上,用戶刷新一次會造成重復登陸的現象。為了解決這個問題,可以使用redis將用戶的session進行集中管理,每次用戶更新或者查詢登陸信息都直接從reids種獲取信息
限數
很多應用出于安全考慮,會再每次進行登陸時,讓用戶輸入驗證碼,但為了短信接口不被頻繁訪問會限制用戶每分鐘獲取驗證碼的頻率,例如一分鐘不能超過5次。
2.3哈希
哈希類型是指鍵值本身又是一個鍵值結構。
Key - value={
{field,value} {field,value} {field,value}...}
2.3.1命令
設置值 hset key field value
獲取值 hget key field
刪除field: hdel field [field...]
計算個數:hlen key
批量操作:
Hmget key field
Hmset key value[field value,field value]
是否存在:hexists key field
獲取所有的field:hkeys key
獲取所有的value:hvals key
獲取所有的field-value:hgetall key
計算value的字符串長度:hstrleng key value
2.3.2內部編碼
Ziplist壓縮列表:當哈希類型元素個數小于hash-max-ziplist-entries配置(默認512個),同時所有值都小于hash-max-ziplist-value配置(默認配置64字節)時,redis會使用ziplist作為內部實現
Hashtable哈希表:當不滿足壓縮列表時自動升級為哈希表,hashtable的讀寫時間復雜度O(1)
2.3.3使用場景
可以將關系型數據庫表記錄的數據(user表)通過userID緩存到redis中。
比如將整個用戶的關聯信息通過json緩存到field中
需要注意兩點哈希類型是稀疏的,而關系型數據庫是完全結構化的。
關系型數據庫可以做復雜的關系查詢,而reids去模擬關系型復雜查詢開發難度高維護成本高
2.4列表
列表用力啊存儲多個有序的字符串,如圖由五個元素組成的列表,列表中的每個字符串成為元素,一個列表最多存2的32次方-1個元素。
再redis中,可以對列表兩端進行插入和彈出,還可以獲取指定范圍的元素列表,獲取指定索引下表的元素。列表是一種比較靈活的數據結構,可以充當棧和隊列的角色,再實際開發中由很多的應用場景。
列表有兩個特點:一.列表中的元素是有序的;二.列表中的元素可以重復。
2.4.1命令
l?添加命令:lpush,rpush,linsert
l?查看: lrange,lindex,llen
l?刪除: lpop,rpop,lrem,ltrim
l?修改: lset
l?阻塞操作:blpop,brpop
從右邊插入元素:rpush key value [value1 value2 value3...]
Rpush listkey a b c d e
?
從左到右查看元素lrange listkey 0 -1
?
向某個元素前后插入元素:linsert key before|after prvot value
Linsert listkey before b net
查找
獲取指定范圍內的元素列表
lrange key start end
lrange操作會獲取列表指定索引范圍所有的元素。索引下標有兩個特點:
第一,索引下標從左到右分別是0到N-1,但從右到左分別是-1到-N。
第二,lrange中的end選項包含了自身。Eg:想獲取列表的第2到第4個元素
獲取列表指定索引下標的元素 lindex key index
Eg:獲取當前列表最后一個元素a
?
lindex listkey -1
獲取當前列表長度llen key
刪除
從列表左側彈出元素
?
刪除指定元素lrem key count value
Lrem命令會從列表中找到等于vlaue元素進行刪除,根據count的不同分為三種情況:
Count>0:從左到右,刪除最多count個元素
Count<0:從右到左,刪除最多count絕對值個元素
Count=0:刪除所有。
例如先向列表中插入4個a,然后刪除列表a左側的4個元素
?
按索引范圍修剪列表元素ltrim key start end
?
修改,修改指定索引下標的元素:lset key index newValue
2.4.2內部編碼
列表類型的內部編碼右兩種。
Ziplist(壓縮列表):當列表的元素個數小于list-max-ziplist-entries配置(默認512個),同時列表種每個元素的值都小于list-max-ziplist-value配置時(默認64字節),redis會選用ziplist來作為列表的內部實現來減少內存的使用。
Linkedlist(鏈表)
2.4.3使用場景
消息隊列
文章列表:每個用戶右屬于自己的文章列表,需要分頁展示文章列表。此時可以考慮使用列表。因為列表不但時有序的,而且支持按索引范圍獲取元素。(文章內容可以使用hash結構來存儲)
2.5集合
集合類型也是用來保存多個字符串元素,但和列表類型不一樣的是集合中不可以有重復元素,并且集合中的元素是無序的,不能通過索引下標獲取元素。Redis除了支持集合內的增刪改查,同時還支持多個集合取交集/并集/差集
2.5.1命令
添加元素:sadd key element [ele ele ele]
刪除元素:srem key element [ele ele ele]
計算元素個數:scard key ?他不會遍歷整個集合而是取內部變量
判斷元素是否在集合中:siselember key element
隨機從集合返回指定個數元素 srandmember key [count]
從集合中隨機彈出元素:spop key
獲取所有集合元素:smembers key
集合間操作
求多個集合的交集:sinter key [key key...]
求多個集合的并集:sunion key [key key...]
求多個集合的差集:sdiff key ?[key key...]
將交集,并集,差集的結果保存
sinterstore destination key ?[key key...]
如上
2.5.2內部編碼
Intset(整數集合):當集合中的元素都是整數且元素個數小于set-max-intset-entries配置(默認512個)時,redis會選用intset來作為集合的內部實現,從而減少內存使用。
Hashtable:當集合類型無法滿足intset的條件時,使用hashtable作為它的內部實現。
2.5.3使用場景
用戶標簽,一個用戶可能有很多的興趣愛好。
2.6有序集合
有序集合保留了集合不能有重復成員的特性,但不同的時,有序集合中的元素可以排序。但是它和列表使用索引下標作為排序依據不同的時,它給每個元素設置一個分數作為排序的依據。注意,元素不能重復但是score可以重復
2.6.2內部編碼
Ziplist(壓縮列表):當有序集合元素個數小于zset-ziplist-entries配置(默認128個),同時每個元素的值都小于zset-max-ziplist-value配置(默認64字節)時,redis會用ziplist來作為有序集合的內部實現。
Skiplist(跳躍表)
2.6.3使用場景
排行榜系統。
2.7鍵管理
2.7.1單個鍵管理
鍵重命名: rename key newkey
如果在rename之前,鍵已經存在,那么它的值也將被覆蓋。為了防止被強行rename,redis提供了renamenx命令,確保只有newkey不存在時才被覆蓋。注意:
由于重命名鍵期間會執行del命令刪除舊鍵,如果鍵對應的值比較大,會存在阻塞的可能性
如果rename和renamenx中的key和newkey如果是相同的,在3.2版本中時可以的,在3.2以前會報錯。
隨機返回一個鍵:randomkey
2.7.2遍歷鍵
Keys [pattern]替代pattern是* ? [] \x
Keys * 獲取所有的鍵
* 代表所有
? 代表匹配一個字符
[] 代表匹配部分字符
\x 用來做轉義;比如要匹配星號則需要轉義
Keys是會造成阻塞所以一般不建議在生產環境上使用
漸進式遍歷
從2.8版本后,提供了一個新的命令scan,它通過漸進式遍歷的方式解決keys在遍歷是帶來的阻塞問題。每次scan命令的時間復雜的是O(1)。但要真正實現keys的功能,需要執行多次scan。
每次執行scan,可以想象成掃描了一個字段中的一部分鍵,直到將字典中的所有鍵遍歷完畢。使用方法:Scan cursor [match pattern] [count number]
Cursor是必須參數,實際上cursor是一個游標,第一次遍歷從0開始,每次scan遍歷完都會返回當前游標的值,直到游標值為0標識遍歷結束。
Match pattern是可選參數,它的作用類似與模式匹配,這點和keys的模式匹配很想。
Count number是可選參數,它的作用是表名每次遍歷鍵的個數默認值是10,可以適當增大。
Scan雖然有效的解決了keys命令可能產生的阻塞問題,但scan并非完美 ,如果在scan的過程中如果有鍵發生了變化(增刪改),那么便利的效果可能會碰到新增的鍵沒有被查到,遍歷出的鍵重復了等情況。
也就是說scan并不能完整的遍歷出所有的鍵。