Redis快速入門視頻課程——筆記(二)

視頻課程鏈接:http://edu.51cto.com/course/14463.html

四、Key操作命令

1. 命令列表

命令用法 解釋
keys pattern 獲取所有匹配pattern參數的Keys。需要說明的是,在我們的正常操作中應該儘量避免對該命令的調用,因爲對於大型數據庫而言,該命令是非常耗時的,對Redis服務器的性能打擊也是比較大的。pattern支持glob-style的通配符格式,如*表示任意一個或多個字符,?表示任意字符,[abc]表示方括號中任意一個字母。
del key [key...] 從數據庫刪除中參數中指定的keys,如果指定鍵不存在,則直接忽略。
exists key 判斷指定鍵是否存在。
move key db 將當前數據庫中指定的鍵Key移動到參數中指定的數據庫中。如果該Key在目標數據庫中已經存在,或者在當前數據庫中並不存在,該命令將不做任何操作並返回0。
rename key newkey 爲指定指定的鍵重新命名,如果參數中的兩個Keys的命令相同,或者是源Key不存在,該命令都會返回相關的錯誤信息。如果newKey已經存在,則直接覆蓋。
renamenx key newkey 如果新值不存在,則將參數中的原值修改爲新值。其它條件和RENAME一致。
persist key 如果Key存在過期時間,該命令會將其過期時間消除,使該Key不再有超時,而是可以持久化存儲。
expire key seconds 該命令爲參數中指定的Key設定超時的秒數,在超過該時間後,Key被自動的刪除。如果該Key在超時之前被修改,與該鍵關聯的超時將被移除。
expireat key timestamp 該命令的邏輯功能和EXPIRE完全相同,唯一的差別是該命令指定的超時時間是絕對時間,而不是相對時間。該時間參數是Unix timestamp格式的,即從1970年1月1日開始所流經的秒數。
ttl key 獲取該鍵所剩的超時描述。
randomkey 從當前打開的數據庫中隨機的返回一個Key。
type key 獲取與參數中指定鍵關聯值的類型,該命令將以字符串的格式返回。

2. 操作

  • keys/del/exists/move/rename/renamenx

    127.0.0.1:6379> flushdb
    OK
    #添加String類型的數據
    127.0.0.1:6379> set mykey 2
    OK
    #添加List類型的數據
    127.0.0.1:6379> lpush mylist a b c
    (integer) 3
    #添加Set類型的數據
    127.0.0.1:6379> sadd myset 1 2 3
    (integer) 3
    #添加Sorted-Set類型的數據
    127.0.0.1:6379> zadd myzset 1 "one" 2 "two"
    (integer) 2
    #添加Hash類型的數據
    127.0.0.1:6379> hset myhash username "tom"
    (integer) 1
    #根據參數中的模式,獲取當前數據庫中符合該模式的所有key,從輸出可以看出,該命令在執行時並不區分與Key關聯的Value類型
    127.0.0.1:6379> keys my*
    1) "myset"
    2) "mykey"
    3) "myzset"
    4) "myhash"
    5) "mylist"
    #刪除了兩個Keys
    127.0.0.1:6379> del mykey mylist
    (integer) 2
    #查看剛剛刪除的Key是否還存在,從返回結果看,mykey確實已經刪除了
    127.0.0.1:6379> exists mykey
    (integer) 0
    #查看一下沒有刪除的Key,以和上面的命令結果進行比較
    127.0.0.1:6379> exists myset
    (integer) 1
    #將當前數據庫中的myset鍵移入到ID爲1的數據庫中
    127.0.0.1:6379> move myset 1
    (integer) 1
    #切換到ID爲1的數據庫
    127.0.0.1:6379> select 1
    OK
    #查看當前數據庫中的所有key
    127.0.0.1:6379[1]> keys *
    1) "myset"
    
    #在重新打開ID爲0的缺省數據庫
    127.0.0.1:6379[1]> select 0
    OK
    #清空數據庫
    127.0.0.1:6379> flushdb
    OK
    #準備新的測試數據 
    127.0.0.1:6379> set mykey "hello"
    OK
    #將mykey改名爲mykey1
    127.0.0.1:6379> rename mykey mykey1
    OK
    #由於mykey已經被重新命名,再次獲取將返回nil
    127.0.0.1:6379> get mykey
    (nil)
    #通過新的鍵名獲取
    127.0.0.1:6379> get mykey1
    "hello"
    #爲renamenx準備測試key
    127.0.0.1:6379> set oldkey "hello"
    OK
    127.0.0.1:6379> set newkey "world"
    OK
    #當新名稱不存在時纔會執行。由於newkey已經存在,因此該命令未能成功執行
    127.0.0.1:6379> renamenx oldkey newkey
    (integer) 0
    #查看newkey的值,發現它並沒有被renamenx覆蓋
    127.0.0.1:6379> get newkey
    "world"
  • ttl/persist/expire/expireat

    127.0.0.1:6379> flushdb
    OK
    #準備測試數據,將該鍵的超時設置爲100秒
    127.0.0.1:6379> set mykey "hello" ex 100
    OK
    #通過ttl命令查看還剩多少秒
    127.0.0.1:6379> ttl mykey
    (integer) 97
    #立刻執行persist命令,該存在超時的鍵變成持久化的鍵,即將該Key的超時去掉
    127.0.0.1:6379> persist mykey
    (integer) 1
    #ttl的返回值告訴我們,該鍵已經沒有超時了
    127.0.0.1:6379> ttl mykey
    (integer) -1
    #爲後面的expire命令準備數據
    127.0.0.1:6379> del mykey
    (integer) 1
    127.0.0.1:6379> set mykey "hello"
    OK
    #設置該鍵的超時被100秒
    127.0.0.1:6379> expire mykey 100
    (integer) 1
    #用ttl命令看當前還剩下多少秒,從結果中可以看出還剩下96秒
    127.0.0.1:6379> ttl mykey
    (integer) 96
    #重新更新該鍵的超時時間爲20秒,從返回值可以看出該命令執行成功
    127.0.0.1:6379> expire mykey 20
    (integer) 1
    #再用ttl確認一下,從結果中可以看出被更新了
    127.0.0.1:6379> ttl mykey
    (integer) 17
    #立刻更新該鍵的值,以使其超時無效。
    127.0.0.1:6379> set mykey "world"
    OK
    #從ttl的結果可以看出,在上一條修改該鍵的命令執行後,該鍵的超時也無效了
    127.0.0.1:6379> ttl mykey
    (integer) -1
  • type/randomkey

    127.0.0.1:6379> del mykey
    (integer) 1
    #添加不同類型的測試數據
    127.0.0.1:6379> set mykey 2
    OK
    127.0.0.1:6379> lpush mylist a b c
    (integer) 3
    127.0.0.1:6379> sadd myset 1 2 3
    (integer) 3
    127.0.0.1:6379> zadd myzset 1 "one" 2 "two"
    (integer) 2
    127.0.0.1:6379> hset myhash username "tom"
    (integer) 1
    #分別查看數據的類型
    127.0.0.1:6379> type mykey
    string
    127.0.0.1:6379> type mylist
    list
    127.0.0.1:6379> type myset
    set
    127.0.0.1:6379> type myzset
    zset
    127.0.0.1:6379> type myhash
    hash
    
    #返回數據庫中的任意鍵
    127.0.0.1:6379> randomkey
    "oldkey"
    #清空當前打開的數據庫
    127.0.0.1:6379> flushdb
    OK
    #由於沒有數據了,因此返回nil
    127.0.0.1:6379> randomkey
    (nil)

五、事務

1. 概述

​ 和其它數據庫一樣,Redis作爲NoSQL數據庫也同樣提供了事務機制。在Redis中,MULTI/EXEC/DISCARD/WATCH這四個命令是我們實現事務的基石。Redis中事務的特徵:
​ 1). 在事務中的所有命令都將會被串行化的順序執行,事務執行期間,Redis不會再爲其它客戶端的請求提供任何服務,從而保證了事物中的所有命令被原子的執行。
​ 2). 和關係型數據庫中的事務相比,在Redis事務中如果有某一條命令執行失敗,其後的命令仍然會被繼續執行。
​ 3). 我們可以通過MULTI命令開啓一個事務,有關係型數據庫開發經驗的人可以將其理解爲"BEGIN TRANSACTION"語句。在該語句之後執行的命令都將被視爲事務之內的操作,最後我們可以通過執行EXEC/DISCARD命令來提交/回滾該事務內的所有操作。這兩個Redis命令可被視爲等同於關係型數據庫中的COMMIT/ROLLBACK語句。
​ 4). 在事務開啓之前,如果客戶端與服務器之間出現通訊故障並導致網絡斷開,其後所有待執行的語句都將不會被服務器執行。然而如果網絡中斷事件是發生在客戶端執行EXEC命令之後,那麼該事務中的所有命令都會被服務器執行。
​ 5). 當使用Append-Only模式時,Redis會通過調用系統函數write將該事務內的所有寫操作在本次調用中全部寫入磁盤。然而如果在寫入的過程中出現系統崩潰,如電源故障導致的宕機,那麼此時也許只有部分數據被寫入到磁盤,而另外一部分數據卻已經丟失。Redis服務器會在重新啓動時執行一系列必要的一致性檢測,一旦發現類似問題,就會立即退出並給出相應的錯誤提示。此時,我們就要充分利用Redis工具包中提供的redis-check-aof工具,該工具可以幫助我們定位到數據不一致的錯誤,並將已經寫入的部分數據進行回滾。修復之後我們就可以再次重新啓動Redis服務器了。

2. 命令列表

命令 解釋
multi 用於標記事務的開始,其後執行的命令都將被存入命令隊列,直到執行EXEC時,這些命令纔會被原子的執行。
exec 執行在一個事務內命令隊列中的所有命令,同時將當前連接的狀態恢復爲正常狀態,即非事務狀態。如果在事務中執行了WATCH命令,那麼只有當WATCH所監控的Keys沒有被修改的前提下,EXEC命令才能執行事務隊列中的所有命令,否則EXEC將放棄當前事務中的所有命令。
discard 回滾事務隊列中的所有命令,同時再將當前連接的狀態恢復爲正常狀態,即非事務狀態。如果WATCH命令被使用,該命令將UNWATCH所有的Keys。

3. 操作

1. 事務被正常執行
#在當前連接上啓動一個新的事務
127.0.0.1:6379> multi
OK
#執行事務中的第一條命令,從該命令的返回結果可以看出,該命令並沒有立即執行,而是存於事務的命令隊列
127.0.0.1:6379> incr t1
QUEUED
#又執行一個新的命令,從結果可以看出,該命令也被存於事務的命令隊列
127.0.0.1:6379> incr t2
QUEUED
#執行事務命令隊列中的所有命令,從結果可以看出,隊列中命令的結果得到返回
127.0.0.1:6379> exec
1) (integer) 1
2) (integer) 1
#只有當提交事務後,在其他連接中才能看到變化

2. 事務中存在失敗的命令
#開啓一個新的事務
127.0.0.1:6379> multi
OK
#設置鍵a的值爲string類型的3
127.0.0.1:6379> set a 3
QUEUED
#從鍵a所關聯的值的頭部彈出元素,由於該值是字符串類型,而lpop命令僅能用於List類型,因此在執行exec命令時,該命令將會失敗
127.0.0.1:6379> lpop a
QUEUED
#再次設置鍵a的值爲字符串4
127.0.0.1:6379> set a 4
QUEUED
#獲取鍵a的值,以便確認該值是否被事務中的第二個set命令設置成功
127.0.0.1:6379> get a
QUEUED
#從結果中可以看出,事務中的第二條命令lpop執行失敗,而其後的set和get命令均執行成功,這一點是Redis的事務與關係型數據庫中的事務之間最爲重要的差別
127.0.0.1:6379> exec
1) OK
2) (error) ERR Operation against a key holding the wrong kind of value
3) OK
4) "4"

3. 回滾事務
#爲鍵t2設置一個事務執行前的值
127.0.0.1:6379> set t2 tt
OK
#開啓一個事務
127.0.0.1:6379> multi
OK
#在事務內爲該鍵設置一個新值
127.0.0.1:6379> set t2 ttnew
QUEUED
#放棄事務
127.0.0.1:6379> discard
OK
#查看鍵t2的值,從結果中可以看出該鍵的值仍爲事務開始之前的值
127.0.0.1:6379> get t2
"tt"

六、主從複製Replication

1. 概述

​ 在Redis中配置Master-Slave模式非常簡單,Redis中主從複製的特點和優勢:
​ 1). 同一個Master可以同步多個Slaves。
​ 2). Slave同樣可以接受其它Slaves的連接和同步請求,可以有效的分載Master的同步壓力,所以可以將Redis的Replication架構視爲圖結構。
​ 3). Master Server是以非阻塞的方式爲Slaves提供服務,所以在Master-Slave同步期間,客戶端仍然可以提交查詢或修改請求。
​ 4). Slave Server同樣是以非阻塞的方式完成數據同步,在同步期間,如果有客戶端提交查詢請求,Redis則返回同步之前的數據。
​ 5). 爲了分載Master的讀操作壓力,Slave服務器可以爲客戶端提供只讀操作的服務,寫服務仍然必須由Master來完成。即便如此,系統的伸縮性還是得到了很大的提高。
​ 6). Master可以將數據保存操作交給Slaves完成,從而避免了在Master中要有獨立的進程來完成此操作。

2. 配置

​ 步驟:

  1. 同時啓動兩個Redis服務器,可以考慮在同一臺機器上啓動兩個Redis服務器,分別監聽不同的端口,如6379和6380

    將配置文件拷貝兩份,並修改端口號

    啓動服務器:

    $ redis-server 6379.conf     #master主服務器
    $ redis-server 6380.conf #slave從服務器
  2. 連接slave服務器,並執行如下命令:

    $ redis-cli -p 6380   #連接從服務器,slave端口號爲6380
    127.0.0.1:6380> slaveof 127.0.0.1 6379 #配置主從關係,指定master的主機地址和端口號
    OK

    上面的方式只是保證了在執行slaveof命令之後,redis_6380成爲了redis_6379的slave,一旦服務(redis_6380)重新啓動之後,他們之間的複製關係將終止。

    如果希望長期保證這兩個服務器之間的Replication關係,可以在redis_6380的配置文件中做如下修改:

    $ vi 6380.conf
    slaveof 127.0.0.1 6379

    這樣就可以保證Redis_6380服務程序在每次啓動後都會主動建立與Redis_6379的Replication連接了。

七、持久化

1. 概述

​ Redis提供的持久化方式:

  1. RDB

    該機制是指在指定的時間間隔內將內存中的數據集快照寫入磁盤。

  2. AOF

    該機制將以日誌的形式記錄服務器所處理的每一個寫操作,在Redis服務器啓動之初會讀取該文件來重新構建數據庫,以保證啓動後數據庫中的數據是完整的。

2. RDB

​ Redis Database:通過單文件的方式來持久化

​ RDB是默認的持久化方式,默認存儲在啓動redis服務器時所在當前目錄下的dump.rdb文件中,一般都會修改存儲在一個固定的目錄中

​ 編輯配置文件:

$ vi myredis.conf
    dbfilename dump.rdb                 #持久化文件的名稱
    #dir  ./                            #持久化文件的目錄,默認爲執行redis-server命令時所在的當前目錄
    dir /home/soft01/software/dump/     #修改存儲位置爲一個固定的目錄

​ 持久化的時機:

  1. 在數據庫關閉時會持久化(需要注意的是在數據庫宕機時不會生成,數據可能會丟失)

  2. 滿足特定條件時會持久化,編輯配置文件:

    $ vi myredis.conf
    save 900 1      #在900秒內,只要有1個key發生變化,就會dump持久化
    save 300 10
    save 60 10000

​ 優缺點:

  • 缺點:可能會丟失數據
  • 優點:效率比較高

3. AOF

​ Append Only File:通過操作日誌的方式來持久化

​ 編輯配置文件:

 $ vi myredis.conf
    appendonly yes                      #開啓aof模式的持久化
    appendfilename "appendonly.aof"     #aof的持久化文件
    appendfsync everysec                #每一秒進行一次持久化操作,可取值:always、everysec、no
    dir /home/soft01/software/dump/     #持久化文件的目錄,與RDB相同

​ 注:可以直接查看生成的appendonly.aof文件,可以認爲是一個日誌文件

​ 優缺點:

  • 缺點:效率比較差
  • 優點:丟失數據量比較少

八、Java訪問Redis

1. 使用Jedis

​ Jedis是一個封裝了redis的java客戶端,集成了redis的一些命令操作,並提供了連接池管理功能

​ 步驟:

  1. 添加依賴

    <dependency>
     <groupId>redis.clients</groupId>
     <artifactId>jedis</artifactId>
     <version>2.9.0</version>
    </dependency>
  2. 基本用法

    public void test01(){
     //獲取jedis的連接
     Jedis jedis=new Jedis("192.168.19.37",6379);
     //驗證
     jedis.auth("itany");
    
     //操作redis
     //jedis.set("name","tom");
     //jedis.set("password","123","nx");
     //System.out.println(jedis.get("name"));
    
     //jedis.lpush("mylist","jack","alice","mike");
     //System.out.println(jedis.lrange("mylist",0,1));
    
     //jedis.sadd("myset","aaa","bbb","ccc");
     //System.out.println(jedis.smembers("myset"));
     //System.out.println();
     //
     //jedis.zadd("myzset",10,"a");
     //jedis.zadd("myzset",20,"b");
     //jedis.zadd("myzset",15,"c");
     //System.out.println(jedis.zrange("myzset",0,-1));
     //System.out.println();
     //
     //jedis.hset("user","name","alice");
     //jedis.hset("user","age","21");
     //Set<String> keys = jedis.hkeys("user");
     //for (String key:keys){
     //    System.out.println(key+"="+jedis.hget("user",key));
     //}
    
     Set<String> keys = jedis.keys("*");
     System.out.println(keys);
    
     //關閉連接
     jedis.close();
    }

2. 使用Spring Data Redis

​ 簡稱SDR,在Spring應用中讀寫Redis數據庫更簡單

​ 基於jedis

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章