Redis開發與運維學習筆記—(4)
- 2020 年 3 月 31 日
- 筆記
———————開始—————-
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"