Redis教程,帶你開啟nosql資料庫的大門
什麼是Redis?
redis是一個key-value儲存系統。和Memcached類似,它支援儲存的value型別相對更多,包括string(字串)、list(連結串列)、set(集合)、zset(sorted set)有序集合)和hash(雜湊型別)。這些資料型別都支援push/pop、add/remove及取交集並集和差集及更豐富的操作,而且這些操作都是原子性的。在此基礎上,redis支援各種不同方式的排序。與memcached一樣,為了保證效率,資料都是快取在記憶體中。區別的是redis會週期性的把更新的資料寫入磁碟或者把修改操作寫入追加的記錄檔案,並且在此基礎上實現了master-slave(主從)同步。
Redis 是一個高效能的key-value資料庫。 redis的出現,很大程度補償了memcached這類key/value儲存的不足,在部 分場合可以對關係資料庫起到很好的補充作用。它提供了Java,C/C++,C#,PHP,JavaScript,Perl,Object-C,Python,Ruby,Erlang等客戶端,使用很方便。
Redis支援主從同步。資料可以從主伺服器向任意數量的從伺服器上同步,從伺服器可以是關聯其他從伺服器的主伺服器。這使得Redis可執行單層樹複製。存檔可以有意無意的對資料進行寫操作。由於完全實現了釋出/訂閱機制,使得從資料庫在任何地方同步樹時,可訂閱一個頻道並接收主伺服器完整的訊息釋出記錄。同步對讀取操作的可擴充套件性和資料冗餘很有幫助。
redis的官網地址,非常好記,是redis.io。(特意查了一下,域名字尾io屬於國家域名,是british Indian Ocean territory,即英屬印度洋領地) 目前,Vmware在資助著redis專案的開發和維護。
概念介紹完了,接下來,我們將一起學習如何使用Redis。
Redis的資料結構-String
Redis支援五種資料型別:string(字串),hash(雜湊),list(列表),set(集合)及zset(sorted set:有序集合)。 其中最常用的為String(字串)和hash(雜湊)兩種型別,接下來,我們先介紹第一種,String型別。
首先需要啟動Redis,連線之後就可以直接操作Redis了,先做一個簡單示例
redis 127.0.0.1:6379> SET name "wumeng"
OK
redis 127.0.0.1:6379> GET name
"wumeng"
上述幾行程式碼,是在記憶體中新建了一個key為name的字串,其值為wumeng,設定鍵使用set命令, 使用get命令可取出相應key的值 ,如上所示get name 值即為wumeng ,需要注意的是,Redis中String型別的值最大隻能儲存512MB
redis 127.0.0.1:6379> del name
(interger)1
上述程式碼表示刪除一個key為name的資料,返回1表示刪除了一條。
Redis中操作String的命令也有很多,示例如下:
1 SET key value 設定指定 key 的值 2 GET key 獲取指定 key 的值。 3 GETRANGE key start end 返回 key 中字串值的子字元 4 GETSET key value 將給定 key 的值設為 value ,並返回 key 的舊值(old value)。 5 GETBIT key offset 對 key 所儲存的字串值,獲取指定偏移量上的位(bit)。 6 MGET key1 [key2…] 獲取所有(一個或多個)給定 key 的值。 7 SETBIT key offset value 對 key 所儲存的字串值,設定或清除指定偏移量上的位(bit)。 8 SETEX key seconds value 將值 value 關聯到 key ,並將 key 的過期時間設為 seconds (以秒為單位)。 9 SETNX key value 只有在 key 不存在時設定 key 的值。 10 SETRANGE key offset value 用 value 引數覆寫給定 key 所儲存的字串值,從偏移量 offset 開始。 11 STRLEN key 返回 key 所儲存的字串值的長度。 12 MSET key value [key value …] 同時設定一個或多個 key-value 對。 13 MSETNX key value [key value …] 同時設定一個或多個 key-value 對,當且僅當所有給定 key 都不存在。 14 PSETEX key milliseconds value 這個命令和 SETEX 命令相似,但它以毫秒為單位設定 key 的生存時間,而不是像 SETEX 命令那樣,以秒為單位。 15 INCR key 將 key 中儲存的數字值增一。 16 INCRBY key increment 將 key 所儲存的值加上給定的增量值(increment) 。 17 INCRBYFLOAT key increment 將 key 所儲存的值加上給定的浮點增量值(increment) 。 18 DECR key 將 key 中儲存的數字值減一。 19 DECRBY key decrement key 所儲存的值減去給定的減量值(decrement) 。 20 APPEND key value 如果 key 已經存在並且是一個字串, APPEND 命令將 value 追加到 key 原來的值的末尾。
Redis的資料結構-Hash
Redis中的Hash類似於集合中的Map,它比較適合用於存放一個物件,示例如下
127.0.0.1:6379> HMSET person name "wumeng" sex "男" age "25"
OK
127.0.0.1:6379> HGETALL person
1) "name"
2) "wumeng"
3) "sex "
4) "男"
5) "age "
6) "25"
也可以使用Hset設定單個,例如
127.0.0.1:6379> HSET person name "wumeng"
OK
127.0.0.1:6379> HGET person name
1) "wumeng"
也可以使用刪除命令刪除一個指定key的資料,示例如下
127.0.0.1:6379> HDEL person name
(integer) 1
Redis中操作Hash的命令也有很多,示例如下:
1 HDEL key field1 [field2] 刪除一個或多個雜湊表字段 2 HEXISTS key field 檢視雜湊表 key 中,指定的欄位是否存在。 3 HGET key field 獲取儲存在雜湊表中指定欄位的值。 4 HGETALL key 獲取在雜湊表中指定 key 的所有欄位和值 5 HINCRBY key field increment 為雜湊表 key 中的指定欄位的整數值加上增量 increment 。 6 HINCRBYFLOAT key field increment 為雜湊表 key 中的指定欄位的浮點數值加上增量 increment 。 7 HKEYS key 獲取所有雜湊表中的欄位 8 HLEN key 獲取雜湊表中欄位的數量 9 HMGET key field1 [field2] 獲取所有給定欄位的值 10 HMSET key field1 value1 [field2 value2 ] 同時將多個 field-value (域-值)對設定到雜湊表 key 中。 11 HSET key field value 將雜湊表 key 中的欄位 field 的值設為 value 。 12 HSETNX key field value 只有在欄位 field 不存在時,設定雜湊表字段的值。 13 HVALS key 獲取雜湊表中所有值 14 HSCAN key cursor [MATCH pattern] [COUNT count] 迭代雜湊表中的鍵值對。
Redis的資料結構-List(列表)
Redis列表是簡單的字串列表,按照插入順序排序。你可以新增一個元素到列表的頭部(左邊)或者尾部(右邊),示例如下
redis 127.0.0.1:6379> LPUSH database_name redis
(integer) 1
redis 127.0.0.1:6379> LPUSH database_name mongodb
(integer) 2
redis 127.0.0.1:6379> LPUSH database_name neo4j
(integer) 3
redis 127.0.0.1:6379> LPUSH database_name mysql
(integer) 4
redis 127.0.0.1:6379> LRANGE database_name 0 10
1) "mysql"
2) "neo4j"
3) "mongodb"
4) "redis"
使用LPUSH 命令進行插入操作,使用LRANGE命令取出指定key的所有集合
Redis中操作List的命令也有很多,示例如下:
1 BLPOP key1 [key2 ] timeout 移出並獲取列表的第一個元素, 如果列表沒有元素會阻塞列表直到等待超時或發現可彈出元素為止。 2 BRPOP key1 [key2 ] timeout 移出並獲取列表的最後一個元素, 如果列表沒有元素會阻塞列表直到等待超時或發現可彈出元素為止。 3 BRPOPLPUSH source destination timeout 從列表中彈出一個值,將彈出的元素插入到另外一個列表中並返回它; 如果列表沒有元素會阻塞列表直到等待超時或發現可彈出元素為止。 4 LINDEX key index 通過索引獲取列表中的元素 5 LINSERT key BEFORE|AFTER pivot value 在列表的元素前或者後插入元素 6 LLEN key 獲取列表長度 7 LPOP key 移出並獲取列表的第一個元素 8 LPUSH key value1 [value2] 將一個或多個值插入到列表頭部 9 LPUSHX key value 將一個值插入到已存在的列表頭部 10 LRANGE key start stop 獲取列表指定範圍內的元素 11 LREM key count value 移除列表元素 12 LSET key index value 通過索引設定列表元素的值 13 LTRIM key start stop 對一個列表進行修剪(trim),就是說,讓列表只保留指定區間內的元素,不在指定區間之內的元素都將被刪除。 14 RPOP key 移除並獲取列表最後一個元素 15 RPOPLPUSH source destination 移除列表的最後一個元素,並將該元素新增到另一個列表並返回 16 RPUSH key value1 [value2] 在列表中新增一個或多個值 17 RPUSHX key value 為已存在的列表新增值
Redis的資料結構-Set
Redis 的 Set 是 String 型別的無序集合。集合成員是唯一的,這就意味著集合中不能出現重複的資料。
redis 127.0.0.1:6379> SADD name wm
(integer) 1
redis 127.0.0.1:6379> SADD name rmx
(integer) 1
redis 127.0.0.1:6379> SADD name hjk
(integer) 1
redis 127.0.0.1:6379> SADD name ycc
(integer) 0
redis 127.0.0.1:6379> SADD name wm
(integer) 0
redis 127.0.0.1:6379> SMEMBERS name
1) "wm"
2) "rmx"
3) "hjk"
4) "ycc"
同樣,使用set集合新增資料使用SADD ,獲取資料使用SMEMBERS 命令
Redis中操作SET的命令也有很多,示例如下:
1 SADD key member1 [member2] 向集合新增一個或多個成員 2 SCARD key 獲取集合的成員數 3 SDIFF key1 [key2] 返回給定所有集合的差集 4 SDIFFSTORE destination key1 [key2] 返回給定所有集合的差集並存儲在 destination 中 5 SINTER key1 [key2] 返回給定所有集合的交集 6 SINTERSTORE destination key1 [key2] 返回給定所有集合的交集並存儲在 destination 中 7 SISMEMBER key member 判斷 member 元素是否是集合 key 的成員 8 SMEMBERS key 返回集合中的所有成員 9 SMOVE source destination member 將 member 元素從 source 集合移動到 destination 集合 10 SPOP key 移除並返回集合中的一個隨機元素 11 SRANDMEMBER key [count] 返回集合中一個或多個隨機數 12 SREM key member1 [member2] 移除集合中一個或多個成員 13 SUNION key1 [key2] 返回所有給定集合的並集 14 SUNIONSTORE destination key1 [key2] 所有給定集合的並集儲存在 destination 集合中 15 SSCAN key cursor [MATCH pattern] [COUNT count] 迭代集合中的元素
Redis 有序集合(sorted set)
Redis 有序集合和集合一樣也是string型別元素的集合,且不允許重複的成員,不同的是每個元素都會關聯一個double型別的分數。redis正是通過分數來為集合中的成員進行從小到大的排序,示例如下
redis 127.0.0.1:6379> ZADD name 1 wm
(integer) 1
redis 127.0.0.1:6379> ZADD name 2 rmx
(integer) 1
redis 127.0.0.1:6379> ZADD name 3 ycc
(integer) 1
redis 127.0.0.1:6379> ZADD name 3 ycc
(integer) 0
redis 127.0.0.1:6379> ZADD name 4 ycc
(integer) 0
redis 127.0.0.1:6379> ZRANGE name 0 10 WITHSCORES
1) "wm"
2) "1"
3) "rmx"
4) "2"
5) "ycc"
6) "4"
sorted set中操作SET的命令也有很多,示例如下:
1 ZADD key score1 member1 [score2 member2] 向有序集合新增一個或多個成員,或者更新已存在成員的分數 2 ZCARD key 獲取有序集合的成員數 3 ZCOUNT key min max 計算在有序集合中指定區間分數的成員數 4 ZINCRBY key increment member 有序集合中對指定成員的分數加上增量 increment 5 ZINTERSTORE destination numkeys key [key …] 計算給定的一個或多個有序集的交集並將結果集儲存在新的有序集合 key 中 6 ZLEXCOUNT key min max 在有序集合中計算指定字典區間內成員數量 7 ZRANGE key start stop [WITHSCORES] 通過索引區間返回有序集合成指定區間內的成員 8 ZRANGEBYLEX key min max [LIMIT offset count] 通過字典區間返回有序集合的成員 9 ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT] 通過分數返回有序集合指定區間內的成員 10 ZRANK key member 返回有序集合中指定成員的索引 11 ZREM key member [member …] 移除有序集合中的一個或多個成員 12 ZREMRANGEBYLEX key min max 移除有序集合中給定的字典區間的所有成員 13 ZREMRANGEBYRANK key start stop 移除有序集合中給定的排名區間的所有成員 14 ZREMRANGEBYSCORE key min max 移除有序集合中給定的分數區間的所有成員 15 ZREVRANGE key start stop [WITHSCORES] 返回有序集中指定區間內的成員,通過索引,分數從高到底 16 ZREVRANGEBYSCORE key max min [WITHSCORES] 返回有序集中指定分數區間內的成員,分數從高到低排序 17 ZREVRANK key member 返回有序集合中指定成員的排名,有序整合員按分數值遞減(從大到小)排序 18 ZSCORE key member 返回有序集中,成員的分數值 19 ZUNIONSTORE destination numkeys key [key …] 計算給定的一個或多個有序集的並集,並存儲在新的 key 中 20 ZSCAN key cursor [MATCH pattern] [COUNT count] 迭代有序集合中的元素(包括元素成員和元素分值)
至此,redis中的五種資料結構到此告一段落,我們知道,Redis資料儲存在記憶體中,因此它擁有高效的讀寫效能,如果redis伺服器因不可抗力宕機或者redis伺服器需要重啟,那麼記憶體中的資料將會消失,為了解決這個問題,我們需要將記憶體持久化到硬碟中,接下來,我們將介紹持久化到資料至硬碟中的兩種方式
Redis的持久化RDB和AOF
Redis持久化方式之一:RDB
RDB持久化是指在指定的時間間隔內將記憶體中的資料集快照寫入磁碟,實際操作過程是fork一個子程序,先將資料集寫入臨時檔案,寫入成功後,再替換之前的檔案,用二進位制壓縮儲存
RDB的優勢:
1). 一旦採用該方式,那麼你的整個Redis資料庫將只包含一個檔案,這對於檔案備份而言是非常完美的。比如,你可能打算每個小時歸檔一次最近24小時的數 據,同時還要每天歸檔一次最近30天的資料。通過這樣的備份策略,一旦系統出現災難性故障,我們可以非常容易的進行恢復。
2). 對於災難恢復而言,RDB是非常不錯的選擇。因為我們可以非常輕鬆的將一個單獨的檔案壓縮後再轉移到其它儲存介質上。
3). 效能最大化。對於Redis的服務程序而言,在開始持久化時,它唯一需要做的只是fork出子程序,之後再由子程序完成這些持久化的工作,這樣就可以極大的避免服務程序執行IO操作了。
4). 相比於AOF機制,如果資料集很大,RDB的啟動效率會更高。
RDB又存在哪些劣勢呢?
1). 如果你想保證資料的高可用性,即最大限度的避免資料丟失,那麼RDB將不是一個很好的選擇。因為系統一旦在定時持久化之前出現宕機現象,此前沒有來得及寫入磁碟的資料都將丟失。
2). 由於RDB是通過fork子程序來協助完成資料持久化工作的,因此,如果當資料集較大時,可能會導致整個伺服器停止服務幾百毫秒,甚至是1秒鐘。
Redis持久化方式之二:AOF AOF持久化以日誌的形式記錄伺服器所處理的每一個寫(插入操作)、刪除操作,查詢操作不會記錄,以文字的方式記錄,可以開啟檔案看到詳細的操作記錄。
AOF的優勢: 1). 該機制可以帶來更高的資料安全性,即資料永續性。Redis中提供了3中同步策略,即每秒同步、每修改同步和不同步。事實上,每秒同步也是非同步完成的,其 效率也是非常高的,所差的是一旦系統出現宕機現象,那麼這一秒鐘之內修改的資料將會丟失。而每修改同步,我們可以將其視為同步持久化,即每次發生的資料變 化都會被立即記錄到磁碟中。可以預見,這種方式在效率上是最低的。至於無同步,無需多言,我想大家都能正確的理解它。
2). 由於該機制對日誌檔案的寫入操作採用的是append模式,因此在寫入過程中即使出現宕機現象,也不會破壞日誌檔案中已經存在的內容。然而如果我們本次操 作只是寫入了一半資料就出現了系統崩潰問題,不用擔心,在Redis下一次啟動之前,我們可以通過redis-check-aof工具來幫助我們解決資料 一致性的問題。
3). 如果日誌過大,Redis可以自動啟用rewrite機制。即Redis以append模式不斷的將修改資料寫入到老的磁碟檔案中,同時Redis還會創 建一個新的檔案用於記錄此期間有哪些修改命令被執行。因此在進行rewrite切換時可以更好的保證資料安全性。
4). AOF包含一個格式清晰、易於理解的日誌檔案用於記錄所有的修改操作。事實上,我們也可以通過該檔案完成資料的重建。
AOF的劣勢:
1). 對於相同數量的資料集而言,AOF檔案通常要大於RDB檔案。RDB 在恢復大資料集時的速度比 AOF 的恢復速度要快。
2). 根據同步策略的不同,AOF在執行效率上往往會慢於RDB。總之,每秒同步策略的效率是比較高的,同步禁用策略的效率和RDB一樣高效。
二者選擇的標準,就是看系統是願意犧牲一些效能,換取更高的快取一致性(aof),還是願意寫操作頻繁的時候,不啟用備份來換取更高的效能,待手動執行save的時候,再做備份(rdb)。
兩種方式的配置
RDB持久化配置 Redis會將資料集的快照dump到dump.rdb檔案中。此外,我們也可以通過配置檔案來修改Redis伺服器dump快照的頻率,在開啟6379.conf檔案之後,我們搜尋save,可以看到下面的配置資訊:
#save 900 1 在900秒(15分鐘)之後,如果至少有1個key發生變化,則dump記憶體快照。
#save 300 10 在300秒(5分鐘)之後,如果至少有10個key發生變化,則dump記憶體快照。
#save 60 10000 在60秒(1分鐘)之後,如果至少有10000個key發生變化,則dump記憶體快照。
AOF持久化配置 在Redis的配置檔案中存在三種同步方式,它們分別是:
#appendfsync always 每次有資料修改發生時都會寫入AOF檔案。
#appendfsync everysec 每秒鐘同步一次,該策略為AOF的預設策略。
appendfsync no 從不同步。高效但是資料不會被持久化。(需要改為yes)
使用Jedis API操作Redis
maven依賴
<dependencies>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.4.2</version>
</dependency>
</dependencies>
使用連線池的方式連線Redis
@Test
pulic void testRedisPool(){
//獲取連線池物件
JedisPoolConfig config = new JedisPoolConfig();
//設定最大連線數
config.setMaxTotal(30);
//設定最大空閒連線數
config.setMaxIdle(10);
//獲取連線
JedisPool jsdisPool = new JedisPool(config,"ip","port");
Jedis jedis = null;
try{
jedis = jedisPool.getResource();
//接下來,就可以使用jedis物件操作Redis
jedis.set("name","吳猛");
String name = jedis.get("name");
}catch(Exception e){
e.printStackTrace();
}finally{
if(jedis!=null){
jedis..close();
}
if(jsdisPool!=null){
jsdisPool.close();
}
}
}
以上程式碼示例是通過連線池的方式獲取Jedis物件,接下來,我們使用Jedis物件操作Redis
與鍵相關的操作
public static void testKey() {
System.out.println("====key功能展示====");
try {
jedis.select(0);
System.out.println("清除資料:" + jedis.flushDB());
System.out.println("判斷某個鍵是否存在:" + jedis.exists("1"));
System.out.println("新增{1,a}鍵值對:" + jedis.set("1", "a"));
System.out.println(jedis.exists("1"));
System.out.println("新增{2,b}鍵值對:" + jedis.set("2", "b"));
System.out.println("系統中所有的鍵如下:" + jedis.keys("*").toString());
System.out.println("刪除鍵 1:" + jedis.del("1"));
System.out.println("判斷鍵 1是否存在:" + jedis.exists("1"));
System.out.println("設定鍵 2的過期時間為5s:" + jedis.expire("2", 5));
TimeUnit.SECONDS.sleep(2);
System.out.println("檢視鍵 2的剩餘生存時間:" + jedis.ttl("2"));
System.out.println("移除鍵 2的生存時間:" + jedis.persist("2"));
System.out.println("檢視鍵 2的剩餘生存時間:" + jedis.ttl("2"));
System.out.println("檢視鍵 2所儲存的值的型別:" + jedis.type("2"));
System.out.println("檢視鍵 2的值:" + jedis.get("2"));
System.out.println("");
} catch (Exception e) {
e.printStackTrace();
}
}
輸出結果:
清除資料:OK
判斷某個鍵是否存在:false
新增{1,a}鍵值對:OK
true
新增{2,b}鍵值對 :OK
系統中所有的鍵如下:[1, 2]
刪除鍵 1:1
判斷鍵 1是否存在:false
設定鍵 2的過期時間為5s:1
檢視鍵 2的剩餘生存時間:3
移除鍵 2的生存時間:1
檢視鍵 2的剩餘生存時間:-1
檢視鍵 2所儲存的值的型別:string
檢視鍵 2的值:b
字串相關操作
public static void testString() {
try {
jedis.select(1);
jedis.flushDB();
System.out.println("====字串功能展示====");
System.out.println("增:");
System.out.println(jedis.set("a", "1"));
System.out.println(jedis.set("b", "2"));
System.out.println(jedis.set("c", "3"));
System.out.println("刪除鍵 a:" + jedis.del("a"));
System.out.println("獲取鍵 a:" + jedis.get("a"));
System.out.println("修改鍵 b:" + jedis.set("b", "bChanged"));
System.out.println("獲取鍵 b 的值:" + jedis.get("b"));
System.out.println("在鍵 c後面加入值:" + jedis.append("c", "End"));
System.out.println("獲取鍵 c的值:" + jedis.get("c"));
System.out.println("增加多個鍵值對:" + jedis.mset("key01", "value01", "key02", "value02", "key03", "value03"));
System.out.println("獲取多個鍵值對:" + jedis.mget("key01", "key02", "key03"));
System.out.println("獲取多個鍵值對:" + jedis.mget("key01", "key02", "key03", "key04"));
System.out.println("刪除多個鍵值對:" + jedis.del(new String[]{"key01", "key02"}));
System.out.println("獲取多個鍵值對:" + jedis.mget("key01", "key02", "key03"));
jedis.flushDB();
System.out.println("新增鍵值對防止覆蓋原先值:");
System.out.println(jedis.setnx("key001", "value001"));
System.out.println(jedis.setnx("key002", "value002"));
System.out.println(jedis.setnx("key002", "value002-new"));
System.out.println("獲取鍵key001的值:" + jedis.get("key001"));
System.out.println("獲取鍵key002的值:" + jedis.get("key002"));
System.out.println("新增鍵值對並設定有效時間:");
System.out.println(jedis.setex("key003", 2, "value003"));
System.out.println("獲取鍵key003的值:" + jedis.get("key003"));
TimeUnit.SECONDS.sleep(3);
System.out.println("獲取鍵key003的值:" + jedis.get("key003"));
System.out.println("獲取原值,更新為新值:");
System.out.println(jedis.getSet("key002", "key2GetSet"));
System.out.println("獲取鍵key002的值:" + jedis.get("key002"));
System.out.println("擷取key002的值的字串:" + jedis.getrange("key002", 2, 5));
System.out.println("");
} catch (Exception e) {
e.printStackTrace();
}
}
輸出結果
====字串功能展示====
增:
OK
OK
OK
刪除鍵 a:1
獲取鍵 a:null
修改鍵 b:OK
獲取鍵 b 的值:bChanged
在鍵 c後面加入值:4
獲取鍵 c的值:3End
增加多個鍵值對:OK
獲取多個鍵值對:[value01, value02, value03]
獲取多個鍵值對:[value01, value02, value03, null]
刪除多個鍵值對:2
獲取多個鍵值對:[null, null, value03]
新增鍵值對防止覆蓋原先值:
1
1
0
獲取鍵key001的值:value001
獲取鍵key002的值:value002
新增鍵值對並設定有效時間:
OK
獲取鍵key003的值:value003
獲取鍵key003的值:null
獲取原值,更新為新值:
value002
獲取鍵key002的值:key2GetSet
擷取key002的值的字串:y2Ge
整數和浮點數相關操作
public static void testNumber() {
try {
jedis.select(2);
jedis.flushDB();
System.out.println("====整數和浮點數功能展示====");
jedis.set("key001", "1");
jedis.set("key002", "2");
jedis.set("key003", "3.3");
System.out.println("獲取鍵key001的值:" + jedis.get("key001"));
System.out.println("獲取鍵key002的值:" + jedis.get("key002"));
System.out.println("將鍵key001的值+1:" + jedis.incr("key001"));
System.out.println("獲取鍵key001的值:" + jedis.get("key001"));
System.out.println("將鍵key002的值-1:" + jedis.decr("key002"));
System.out.println("獲取鍵key002的值:" + jedis.get("key002"));
System.out.println("將key001的值加上整數5:" + jedis.incrBy("key001", 5));
System.out.println("獲取key001的值:" + jedis.get("key001"));
System.out.println("將key002的值減去整數5:" + jedis.decrBy("key002", 5));
System.out.println("獲取key002的值:" + jedis.get("key002"));
System.out.println("");
} catch (Exception e) {
e.printStackTrace();
}
}
輸出結果
====整數和浮點數功能展示====
獲取鍵key001的值:1
獲取鍵key002的值:2
將鍵key001的值+1:2
獲取鍵key001的值:2
將鍵key002的值-1:1
獲取鍵key002的值:1
將key001的值加上整數5:7
獲取key001的值:7
將key002的值減去整數5:-4
獲取key002的值:-4
List(列表)相關操作 Redis 列表是簡單的字串列表,按照插入順序排序。你可以新增一個元素到列表的頭部(左邊)或者尾部(右邊)。
public static void testList() {
jedis.select(3);
jedis.flushDB();
System.out.println("====列表list功能展示====");
jedis.lpush("collections", "ArrayList", "LinkedList", "Vector", "Stack", "queue");
jedis.lpush("collections", "HashMap");
jedis.lpush("collections", "HashMap");
jedis.lpush("collections", "HashMap");
jedis.lpush("collections", "HashMap");
jedis.lpush("number", "1");
jedis.lpush("number", "2");
jedis.lpush("number", "3");
// -1 代表倒數第一個
System.out.println("collections 的內容:" + jedis.lrange("collections", 0, -1));
System.out.println("collections區間0-2內容:" + jedis.lrange("collections", 0, 2));
System.out.println("=================");
// 刪除列表指定的值 ,第二個引數為刪除的個數(有重複時),後add進去的值先被刪,類似於出棧
System.out.println("刪除指定元素個數:" + jedis.lrem("collections", 2, "HashMap"));
System.out.println("collections 的內容:" + jedis.lrange("collections", 0, -1));
System.out.println("刪除區間0-4以外的資料:" + jedis.ltrim("collections", 0, 4));
System.out.println("collections 的內容:" + jedis.lrange("collections", 0, -1));
System.out.println("collections列表出棧(左端):" + jedis.lpop("collections"));
System.out.println("collections的內容:" + jedis.lrange("collections", 0, -1));
System.out.println("collections新增元素,從列表右端,與lpush相對應:" + jedis.rpush("collections", "EnumMap"));
System.out.println("collections的內容:" + jedis.lrange("collections", 0, -1));
System.out.println("collections列表出棧(右端):" + jedis.rpop("collections"));
System.out.println("collections的內容:" + jedis.lrange("collections", 0, -1));
System.out.println("修改collections指定下標1的內容:" + jedis.lset("collections", 1, "LinkedArrayList"));
System.out.println("collections的內容:" + jedis.lrange("collections", 0, -1));
System.out.println("=================");
System.out.println("collections的長度:" + jedis.llen("collections"));
System.out.println("獲取collections下標為2的元素:" + jedis.lindex("collections", 2));
System.out.println("=================");
jedis.lpush("sortedList", "3", "6", "2", "0", "7", "4");
System.out.println("sortedList排序前:" + jedis.lrange("sortedList", 0, -1));
System.out.println(jedis.sort("sortedList"));
System.out.println("sortedList排序後:" + jedis.lrange("sortedList", 0, -1));
System.out.println("");
}
輸出結果
====列表list功能展示====
collections 的內容:[HashMap, HashMap, HashMap, HashMap, queue, Stack, Vector, LinkedList, ArrayList]
collections區間0-2內容:[HashMap, HashMap, HashMap]
=================
刪除指定元素個數:2
collections 的內容:[HashMap, HashMap, queue, Stack, Vector, LinkedList, ArrayList]
刪除區間0-4以外的資料:OK
collections 的內容:[HashMap, HashMap, queue, Stack, Vector]
collections列表出棧(左端):HashMap
collections的內容:[HashMap, queue, Stack, Vector]
collections新增元素,從列表右端,與lpush相對應:5
collections的內容:[HashMap, queue, Stack, Vector, EnumMap]
collections列表出棧(右端):EnumMap
collections的內容:[HashMap, queue, Stack, Vector]
修改collections指定下標1的內容:OK
collections的內容:[HashMap, LinkedArrayList, Stack, Vector]
=================
collections的長度:4
獲取collections下標為2的元素:Stack
================
sortedList排序前:[4, 7, 0, 2, 6, 3]
[0, 2, 3, 4, 6, 7]
sortedList排序後:[4, 7, 0, 2, 6, 3]
集合(Set)相關操作 Redis的Set是string型別的無序集合。 集合是通過雜湊表實現的,所以新增,刪除,查詢的複雜度都是O(1)。
public static void testSet() {
try {
jedis.select(4);
jedis.flushDB();
System.out.println("========測試集合(set)=========");
System.out.println("集合set新增資料:" + jedis.sadd("setElement", "e1", "e7", "e3", "e6", "e0", "e4"));
System.out.println(jedis.sadd("setElement", "e6"));
System.out.println("setElement的所有元素:" + jedis.smembers("setElement"));
System.out.println("刪除元素e0:" + jedis.srem("setElement", "e0"));
System.out.println("setElement的所有元素:" + jedis.smembers("setElement"));
System.out.println("刪除兩個元素e7和e6:" + jedis.srem("setElement", "e7", "e6"));
System.out.println("setElement的所有元素為:" + jedis.smembers("setElement"));
System.out.println("隨機的移除集合中的一個元素:" + jedis.spop("setElement"));
System.out.println("隨機的移除集合中的一個元素:" + jedis.spop("setElement"));
System.out.println("setElement的所有元素為:" + jedis.smembers("setElement"));
System.out.println("setElement中包含元素的個數:" + jedis.scard("setElement"));
System.out.println("e3是否在setElement中:" + jedis.sismember("setElement", "e3"));
System.out.println("e1是否在setElement中:" + jedis.sismember("setElement", "e1"));
System.out.println("=================");
System.out.println(jedis.sadd("setElement1", "e1", "e2", "e4", "e3", "e0", "e8", "e7", "e5"));
System.out.println(jedis.sadd("setElement2", "e1", "e2", "e4", "e3", "e0", "e8"));
System.out.println("將setElement1中刪除e1並存入setElement3中:" + jedis.smove("setElement1", "setElement3", "e1"));
System.out.println("將setElement1中刪除e2並存入setElement3中:" + jedis.smove("setElement1", "setElement3", "e2"));
System.out.println("setElement1中的元素:" + jedis.smembers("setElement1"));
System.out.println("setElement3中的元素:" + jedis.smembers("setElement3"));
System.out.println("集合運算:");
System.out.println("setElement1中的元素:" + jedis.smembers("setElement1"));
System.out.println("setElement2中的元素:" + jedis.smembers("setElement2"));
System.out.println("setElement1和setElement2的交集:" + jedis.sinter("setElement1", "setElement2"));
System.out.println("setElement1和setElement2的並集:" + jedis.sunion("setElement1", "setElement2"));
// setElement1中有,setElement2中沒有
System.out.println("setElement1和setElement2的差集:" + jedis.sdiff("setElement1", "setElement2"));
System.out.println("");
} catch (Exception e) {
e.printStackTrace();
}
}
輸出結果:
========測試集合(set)=========
集合set新增資料:6
0
setElement的所有元素:[e3, e6, e1, e7, e0, e4]
刪除元素e0:1
setElement的所有元素:[e6, e3, e1, e7, e4]
刪除兩個元素e7和e6:2
setElement的所有元素為:[e3, e1, e4]
隨機的移除集合中的一個元素:e3
隨機的移除集合中的一個元素:e4
setElement的所有元素為:[e1]
setElement中包含元素的個數:1
e3是否在setElement中:false
e1是否在setElement中:true
=================
8
6
將setElement1中刪除e1並存入setElement3中:1
將setElement1中刪除e2並存入setElement3中:1
setElement1中的元素:[e5, e8, e3, e7, e0, e4]
setElement3中的元素:[e1, e2]
集合運算:
setElement1中的元素:[e5, e8, e3, e7, e0, e4]
setElement2中的元素:[e3, e4, e2, e8, e1, e0]
setElement1和setElement2的交集:[e3, e4, e8, e0]
setElement1和setElement2的並集:[e5, e8, e3, e1, e7, e0, e2, e4]
setElement1和setElement2的差集:[e5, e7]
hash相關操作 Redis hash 是一個鍵值(key=>value)對集合。 Redis hash是一個string型別的field和value的對映表,hash特別適合用於儲存物件。
public static void testHash() {
try {
System.out.println("=======集合(Set)=======");
jedis.select(5);
jedis.flushDB();
Map<String, String> map = new HashMap<String, String>();
map.put("key001", "value001");
map.put("key002", "value002");
map.put("key003", "value003");
jedis.hmset("hash", map);
jedis.hset("hash", "key004", "value004");
// return Map<String,String>
System.out.println("雜湊hash的所有鍵值對為:" + jedis.hgetAll("hash"));
// return Set<String>
System.out.println("雜湊hash的所有鍵為:" + jedis.hkeys("hash"));
// return List<String>
System.out.println("雜湊hash的所有值為:" + jedis.hvals("hash"));
System.out.println("將key006儲存的值加上一個整數,如果key006不存在則新增key006:" + jedis.hincrBy("hash", "key006", 6));
System.out.println("雜湊hash的所有鍵值對為:" + jedis.hgetAll("hash"));
System.out.println("將key006儲存的值加上一個整數,如果key006不存在則新增key006:" + jedis.hincrBy("hash", "key006", 3));
System.out.println("雜湊hash的所有鍵值對為:" + jedis.hgetAll("hash"));
System.out.println("刪除一個或者多個鍵值對:" + jedis.hdel("hash", "key002"));
System.out.println("雜湊hash的所有鍵值對為:" + jedis.hgetAll("hash"));
System.out.println("雜湊hash中鍵值對的個數:" + jedis.hlen("hash"));
System.out.println("判斷hash中是否存在key002:" + jedis.hexists("hash", "key002"));
System.out.println("判斷hash中是否存在key003:" + jedis.hexists("hash", "key003"));
System.out.println("獲取hash中的值:" + jedis.hmget("hash", "key003"));
System.out.println("獲取hash中的值:" + jedis.hmget("hash", "key003", "key004"));
System.out.println("");
} catch (Exception e) {
e.printStackTrace();
}
}
輸出結果:
=======集合(Set)=======
雜湊hash的所有鍵值對為:{key004=value004, key003=value003, key002=value002, key001=value001}
雜湊hash的所有鍵為:[key004, key003, key002, key001]
雜湊hash的所有值為:[value001, value003, value002, value004]
將key006儲存的值加上一個整數,如果key006不存在則新增key006:6
雜湊hash的所有鍵值對為:{key004=value004, key003=value003, key006=6, key002=value002, key001=value001}
將key006儲存的值加上一個整數,如果key006不存在則新增key006:9
雜湊hash的所有鍵值對為:{key004=value004, key003=value003, key006=9, key002=value002, key001=value001}
刪除一個或者多個鍵值對:1
雜湊hash的所有鍵值對為:{key004=value004, key003=value003, key006=9, key001=value001}
雜湊hash中鍵值對的個數:4
判斷hash中是否存在key002:false
判斷hash中是否存在key003:true
獲取hash中的值:[value003]
獲取hash中的值:[value003, value004]
有序集合相關操作 zset(sorted set:有序集合) Redis zset 和 set 一樣也是string型別元素的集合,且不允許重複的成員。 不同的是每個元素都會關聯一個double型別的分數。redis正是通過分數來為集合中的成員進行從小到大的排序。 zset的成員是唯一的,但分數(score)卻可以重複。
public static void testSortSet() {
try {
System.out.println("=======有序集合=======");
jedis.select(6);
jedis.flushDB();
Map<String, Double> map = new HashMap<String, Double>();
map.put("key2", 1.2);
map.put("key3", 4.0);
map.put("key4", 5.0);
map.put("key5", 0.2);
System.out.println(jedis.zadd("zset", 3, "key1"));
System.out.println(jedis.zadd("zset", map));
System.out.println("zset中的所有元素:" + jedis.zrange("zset", 0, -1));
System.out.println("zset中的所有元素:" + jedis.zrangeWithScores("zset", 0, -1));
System.out.println("zset中的所有元素:" + jedis.zrangeByScore("zset", 0, 100));
System.out.println("zset中的所有元素:" + jedis.zrangeByScoreWithScores("zset", 0, 100));
System.out.println("zset中key2的分值:" + jedis.zscore("zset", "key2"));
System.out.println("zset中key2的排名:" + jedis.zrank("zset", "key2"));
System.out.println("刪除zset中的元素key3:" + jedis.zrem("zset", "key3"));
System.out.println("zset中的所有元素:" + jedis.zrange("zset", 0, -1));
System.out.println("zset中元素的個數:" + jedis.zcard("zset"));
System.out.println("zset中分值在1-4之間的元素的個數:" + jedis.zcount("zset", 1, 4));
System.out.println("key2的分值加上5:" + jedis.zincrby("zset", 5, "key2"));
System.out.println("key3的分值加上4:" + jedis.zincrby("zset", 4, "key3"));
System.out.println("zset中的所有元素:" + jedis.zrange("zset", 0, -1));
System.out.println("");
} catch (Exception e) {
e.printStackTrace();
}
}
輸出結果:
=======有序集合=======
1
4
zset中的所有元素:[key5, key2, key1, key3, key4]
zset中的所有元素:[[[107, 101, 121, 53],0.2], [[107, 101, 121, 50],1.2], [[107, 101, 121, 49],3.0], [[107, 101, 121, 51],4.0], [[107, 101, 121, 52],5.0]]
zset中的所有元素:[key5, key2, key1, key3, key4]
zset中的所有元素:[[[107, 101, 121, 53],0.2], [[107, 101, 121, 50],1.2], [[107, 101, 121, 49],3.0], [[107, 101, 121, 51],4.0], [[107, 101, 121, 52],5.0]]
zset中key2的分值:1.2
zset中key2的排名:1
刪除zset中的元素key3:1
zset中的所有元素:[key5, key2, key1, key4]
zset中元素的個數:4
zset中分值在1-4之間的元素的個數:2
key2的分值加上5:6.2
key3的分值加上4:4.0
zset中的所有元素:[key5, key1, key3, key4, key2]