Redis開發與運維學習筆記—(4)

  • 2020 年 3 月 31 日
  • 筆記

redis中針對單個鍵有很多命令,之前我們已經接觸到了type、del、object、exists、expire等等,再來看其他命令。開始之前,來看一個小插曲:

———————開始—————-

set hello world的時候,竟然提示read-only。使用info replication的方法查看當前複製狀態,發現role變成了slave,所以使用slaveof no one來修改下屬性。

[root@VM_48_10_centos ~]# redis-cli -h 127.0.0.1 -p 6379  127.0.0.1:6379> set hello world  (error) READONLY You can't write against a read only slave.  127.0.0.1:6379> info replication  # Replication  role:slave  master_host:xxx.xx.5.121  master_port:20556  master_link_status:down  master_last_io_seconds_ago:-1  master_sync_in_progress:0  slave_repl_offset:1  master_link_down_since_seconds:1585363887  slave_priority:100  slave_read_only:1  connected_slaves:0  master_repl_offset:0  repl_backlog_active:0  repl_backlog_size:1048576  repl_backlog_first_byte_offset:0  repl_backlog_histlen:0  127.0.0.1:6379> slaveof no one  OK  127.0.0.1:6379> set hello world  OK

———————小插曲結束—————-

正式開始看其他鍵操作

1

鍵重命名

rename key newkey

舉例如下:

127.0.0.1:6379> get hello  "world"  127.0.0.1:6379> rename hello hi  OK  127.0.0.1:6379> get hello  (nil)  127.0.0.1:6379> get hi  "world"  127.0.0.1:6379> set hello world2  OK  127.0.0.1:6379> get hello  "world2"  127.0.0.1:6379> rename hi hello  OK  127.0.0.1:6379> get hello  "world"  127.0.0.1:6379> get hi  (nil)  

收件創建hello–>world鍵值對,然後將hello重命名為hi,發現hello鍵的value為空,而hi鍵的value為world,再重新設置hello,再次重命名,發現hello鍵被覆蓋。

通過這個例子,我們發現,使用rename操作是有可能覆蓋已經存在的鍵值的,這在線上可能不安全,因此,redis提供了renamenx命令,表示僅在rename的新鍵不存在的時候,在進行重命名,如果存在,則重命名返回數字0,而不是返回ok,這樣避免了線上的鍵被覆蓋。

除此之外,還有2點需要注意:

1、由於重命名期間會執行del命令刪除舊的鍵,如果鍵對應的值比較大,則會存在阻塞redis的風險。這一點和MySQL中的rename不同,mysql中的rename操作為原子操作,本質上是對底層文件句柄的操作。

2、如果key和newkey相同,在3.2版本之前返回錯誤,在3.2版本之後,返回0

2

隨機返回一個鍵

使用randomkey可以隨機返回一個鍵。這個功能可以測試當前redis中是否有鍵值

3

鍵過期

expire和expireat

關於鍵過期,之前說過expire的命令,該命令可以通過:

expire key seconds

來讓鍵在seconds秒之後過期。

但是,這個命令不夠精確,我們可以使用expireat命令來指定精確的過期時間:

expireat key timestamp:鍵在秒級時間戳timestamp之後過期。其中timestamp需要取整數。

ttl和pttl

這兩個命令是查看redis的鍵剩餘過期時間的。pttl精度更高,可以達到毫秒級別,有3種返回值:

1、大於0的整數,值得是鍵剩餘過期時間

2、返回1,代表鍵沒有設置過期時間

3、返回-2,代表鍵不存在

127.0.0.1:6379> set hello world  OK  127.0.0.1:6379> expire hello 10  (integer) 1  127.0.0.1:6379> ttl hello  (integer) 7  127.0.0.1:6379> pttl hello  (integer) 4461  

毫秒級過期方案pexpire和pexpireat

這兩兄弟和expire不同之處在於,最後跟的時間是毫秒。其他的使用方法都一樣,本質上,redis會將expire的命令轉換成pexpire的命令。

幾點注意:

a、如果expire的鍵不存在,則會返回0

b、如果時間為負值,則鍵會被立即刪除。

127.0.0.1:6379> get hello  "world"  127.0.0.1:6379>  127.0.0.1:6379> expire hello -2  (integer) 1  127.0.0.1:6379> get hello  (nil)  127.0.0.1:6379> expire hello 10  (integer) 0  

c、persist命令可以將鍵的過期時間清除

127.0.0.1:6379> set hello world  OK  127.0.0.1:6379> expire hello 50  (integer) 1  127.0.0.1:6379> ttl hello  (integer) 46  127.0.0.1:6379> persist hello  (integer) 1  127.0.0.1:6379> ttl hello  (integer) -1  127.0.0.1:6379> get hello  "world"  

d、set命令會導致過期時間失敗

127.0.0.1:6379> get hello  "world"  127.0.0.1:6379> expire hello 50  (integer) 1  127.0.0.1:6379> ttl hello  (integer) 47  127.0.0.1:6379> set hello world~~  OK  127.0.0.1:6379> ttl hello  (integer) -1  

e、redis不支持二級數據結構(哈希、列表)內部元素的過期功能。

f、setex命令作為set+expire的組合,不但是原子執行,同時減少了一次網絡通訊時間。

4

遷移鍵

redis中,提供了3中遷移鍵的方法:

move

dump+restore

migrate

下面分別介紹:

1、move

move命令用戶在多個數據庫中進行鍵遷移。它的主要功能是將鍵從一個數據庫遷移到另外一個數據庫,但是,多數據庫的功能,本身是不建議在線上使用的,這個命令大家了解一下即可。

127.0.0.1:6379> get hello  "world~~"  127.0.0.1:6379> move hello 1  (integer) 1  127.0.0.1:6379> get hello  (nil)  127.0.0.1:6379> select 1  OK  127.0.0.1:6379[1]> get hello  "world~~"  

2、dump+restore

dump+restore可以實現在不同的redis實例之間進行數據遷移的功能,整個遷移的過程分為兩步:

a、在源redis上,dump命令會將鍵值序列化,格式採用的是rdb格式。

b、在目標redis上,restore命令將上面序列化的值進行復原,其中ttl參數代表過期時間。

這裡有2點需要注意:

第一:dump+restore並非原子性的,而是通過客戶端分佈完成的。

第二:遷移過程是開啟了2個客戶端的連接,所以dump的結果不是在源redis和目標redis之間進行傳輸,需要有個中間過程。

舉例如下:

###6379端口  127.0.0.1:6379> get hello  "world~~"  127.0.0.1:6379> dump hello  "x00aworld~~x06x00xe9x02ixcfnxd0xa5:"    ###6380端口  127.0.0.1:6380> get hello  (nil)  127.0.0.1:6380> restore hello 0 "x00aworld~~x06x00xe9x02ixcfnxd0xa5:"  OK  127.0.0.1:6380> get hello  "world~~"  

3、migrate

該命令也是在redis實例間進行數據遷移的,實際上migrate命令就是講dump、restore、del3個命令進行組合,從而簡化了操作流程。

它跟dump+restore的方法有3點不同:

第一、整個過程是源自執行的,不需要要在多個redis實例上開啟客戶端,只需要在源redis上執行migrate命令即可

第二、migrate命令的數據傳輸直接在源redis和目標redis上完成的

第三、目標redis完成restore後發送ok給源redis,源redis接受後會根據migrate對應的選項來決定是否在源redis上刪除對應的鍵。

migrate的參數如下:

host:目標redis的IP地址

port:目標redis的端口

key|「」 :redis3.0.6之前,migrate只支持遷移一個鍵,當需要遷移多個鍵,此處字符串為空

destination-db:目標redis的數據庫索引,例如要遷移到0號數據庫,此處寫0即可。

timeout:遷移的超時時間

copy:添加該參數,遷移之後不刪除源鍵

replace:添加改參數,會覆蓋目標端redis的鍵

keys key [key1 key2]:遷移多個鍵的時候用,如果要遷移多個,則使用keys key1 key2 key3

下面我們從6379端口將鍵遷移到6380端口:

127.0.0.1:6379> flushdb  OK  127.0.0.1:6379> set yeyz handsome  OK  127.0.0.1:6379> get yeyz  "handsome"  127.0.0.1:6379> migrate 127.0.0.1 6380 yeyz 0 1000  OK  127.0.0.1:6379> get yeyz  (nil)  127.0.0.1:6379> exit  [root@VM_48_10_centos ~]# redis-cli -p 6380  127.0.0.1:6380> get yeyz  "handsome"  

注意:

a、如果沒有加replace參數,但是目標端已經有同名鍵了,此時會報錯,提示busykey target key name already exists.

b、如果源redis沒有要遷移的鍵,則會提示nokey

最後,批量遷移舉例:

[root@VM_48_10_centos ~]# redis-cli  127.0.0.1:6379> set key0 value0  OK  127.0.0.1:6379> set key1 value1  OK  127.0.0.1:6379> set key2 value2  OK  127.0.0.1:6379> migrate 127.0.0.1 6380 "" 0 1000 keys key0 key1 key2  OK  127.0.0.1:6379> get key0  (nil)  127.0.0.1:6379> get key1  (nil)  127.0.0.1:6379> get key2  (nil)  127.0.0.1:6379> exit    [root@VM_48_10_centos ~]# redis-cli -p 6380  127.0.0.1:6380> get key0  "value0"  127.0.0.1:6380> get key1  "value1"  127.0.0.1:6380> get key2  "value2"