天天看點

高可用Redis(一):通用指令,資料結構和内部編碼,單線程架構

1.通用API

1.1 keys指令和dbsize指令

keys *              周遊所有key
keys [pattern]      周遊模式下所有的key
dbsize              計算Redis中所有key的總數           

例子:

127.0.0.1:6379> set hello world
OK
127.0.0.1:6379> set php good
OK
127.0.0.1:6379> set python best
OK
127.0.0.1:6379> keys *          # 檢視Redis中所有的key
1) "hello"
2) "python"
3) "php"
127.0.0.1:6379> dbsize          # 檢視Redis中key的總數
(integer) 3
127.0.0.1:6379> keys p*         # 檢視Redis中以p開頭的所有的key
1) "python"
2) "php"
127.0.0.1:6379> set perl aaa
OK
127.0.0.1:6379> set c++ bbb
OK
127.0.0.1:6379> keys p*          # 檢視Redis中所有的key
1) "python"
2) "php"
3) "perl"
127.0.0.1:6379> dbsize          # 檢視Redis中key的總數
(integer) 5
127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3 k4 v4
OK
127.0.0.1:6379> dbsize          # 檢視Redis中key的總數
(integer) 9           

注意事項:

!.keys指令的時間複雜度為O(n)
2.在生産環境中,使用keys指令取出所有key并沒有什麼意義,而且Redis是單線程應用,如果Redis中存的key很多,使用keys指令會阻塞其他指令執行,是以keys指令一般不在生産環境中使用
3.dbsize指令的時間複雜度是O(1)
4.Redis内置一個計數器,可以實時更新Redis中key的總數,是以dbsize指令可以線上上使用           

1.2 exists指令和del指令

exists key              判斷一個key是否存在
del key [key...]        删除指定的key-value           
127.0.0.1:6379> set k1 v1
OK
127.0.0.1:6379> set k2 v2
OK
127.0.0.1:6379> exists k1       # 判斷k1是否存在
(integer) 1     
127.0.0.1:6379> exists k2       # 判斷k2是否存在
(integer) 1
127.0.0.1:6379> del k1          # 删除k1這個鍵值對
(integer) 1
127.0.0.1:6379> exists k1       # 判斷k1是否存在,0表示不存在 
(integer) 0
127.0.0.1:6379> exists k2       # 判斷k2是否存在,1表示key存在
(integer) 1
127.0.0.1:6379> set a1 b1 
OK
127.0.0.1:6379> set a2 b2
OK
127.0.0.1:6379> del a1 a2       # 删除a1和a2鍵值對
(integer) 2           
del指令和exists指令的時間複雜度為O(1)           

1.3 expire指令,ttl指令和persist指令

expire key seconds      設定key的過期時間,多少seconds後過期
ttl key                 檢視key剩餘的過期時間
persist key             去掉key的過期時間           
127.0.0.1:6379> set hello world
OK
127.0.0.1:6379> expire hello 20
(integer) 1             # 設定hello這個key的過期時間為20秒
127.0.0.1:6379> ttl hello
(integer) 17            # 還有17秒過期
127.0.0.1:6379> ttl hello
(integer) 11            # 還有11秒過期
127.0.0.1:6379> get hello
"world"
127.0.0.1:6379> ttl hello
(integer) 5             # 還有5秒過期
127.0.0.1:6379> ttl hello
(integer) -2            # -2表示key已經不存在了 
127.0.0.1:6379> set hello world
OK
127.0.0.1:6379> expire hello 20
(integer) 1             # 設定hello這個key的過期時間為20秒
127.0.0.1:6379> ttl hello
(integer) 15            # 還有15秒過期
127.0.0.1:6379> persist hello
(integer) 1             # 删除hello的過期時間
127.0.0.1:6379> ttl hello 
(integer) -1            # -1表示key存在,并且沒有過期時間
127.0.0.1:6379> get hello
"world"           
expire指令和ttl指令,persist指令的時間複雜度都是O(1)           

1.4 type指令

type key        # 傳回key的類型           
127.0.0.1:6379> set a b
OK
127.0.0.1:6379> type a
string
127.0.0.1:6379> sadd myset 1 2 3
(integer) 3
127.0.0.1:6379> type myset
set
127.0.0.1:6379> type abc        # 檢視一個不存在的key時,傳回None,表示key不存在
none           
type的傳回結果有6種:string,hash,list,set,zset,none
type指令的時間複雜度為O(1)           

2.資料結構和内部編碼

Redis每種資料結構及對應的内部編碼如下圖所示

高可用Redis(一):通用指令,資料結構和内部編碼,單線程架構

3.單線程架構

Redis内部使用單線程架構。

比如一條公路,這條公路隻有一條車道。所有從這條車道上行駛的車,都必須按先來後到的順序依次行駛

Redis一個瞬間隻能執行一條指令,不能執行兩條指令

3.1 Redis單線程為什麼這麼快

1.純記憶體
Redis把所有的資料都儲存在記憶體中,而記憶體的響應速度是非常快的

2.非阻塞IO
Redis使用epoll異步非阻塞模型
Redis自身實作了事件處理

3.避免線程切換和競态消耗
在使用多線程程式設計中,線程之間的切換也會消耗一部分CPU資源,
如果不合理的實作多線程程式設計,可能比單線程還要慢           

注意事項:

一次隻運作一條指令
拒絕長(慢)指令
    keys 
    flushall
    flushdb
    slow lua script
    mutil/exec
    operate