Jedis入門
在Maven中,添加如下依賴即可使用:
<dependency> <groupId>commons-pool</groupId> <artifactId>commons-pool</artifactId> <version>1.6</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>compile</scope> </dependency>
1.簡單配置-連接操作
/**簡單連接Redis方式 * 1)創建連接 * 2)使用連接進行操作 * 3)關閉連接 */ @Test public void connectionTest() { //1)創建連接 Jedis connection = new Jedis("192.168.36.130", 6379); connection.auth("123456"); //2)使用連接進行操作 connection.set("name", "武大郎"); connection.set("age","26"); System.out.println(" 姓名:"+connection.get("name")+" 年齡:"+connection.get("age")); //3)關閉連接 connection.close(); }
2.連接池配置-連接池操作
/** *連接池連接Redis方式 * * 1)創建連接池配置對象 * 2)配置相應的值 * 3)通過配置對象創建連接池對象 * 4)通過連接池獲取連接 * 5)執行操作 * 6)釋放連接 */ @Test public void connectionPoolTest() { //1 創建連接池配置對象 JedisPoolConfig config = new JedisPoolConfig(); //2 進行配置-四個配置 config.setMaxIdle(2);//最小連接(空閑最大連接) config.setMaxTotal(10);//最大連接數 config.setMaxWaitMillis(2 * 1000);//最大等待時間 config.setTestOnBorrow(true);//獲取連接時測試連接是否暢通 JedisPool pool = new JedisPool(config, "192.168.36.130", 6379, 2 * 1000, "123456"); //3 通過配置對象創建連接池對象 Jedis connection = pool.getResource(); //4 通過連接池獲取連接 //5 執行操作-設置值和獲取值 connection.set("name", "武大郎-testPool"); connection.set("age","26"); System.out.println("姓名:"+connection.get("name")+" 年齡:"+connection.get("age")); //6 釋放連接 connection.close();//釋放和關閉公用一個方法,底層自動判斷,如果是連接池環境則釋放,否則關閉. pool.close();; }
Redis數據類型
Redis中的數據類型有:
- 字符串(String)
- 列表(list)
- 有序集合(sorted set)
- 散列(hash)
下面就分別介紹這五種數據類型及其相應的操作命令。(示例文檔)
Jedis數據結構操作
工具抽取
package net.riking.redis.connection.utils; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import redis.clients.jedis.JedisPoolConfig; public class JedisConnectionUtils { private static JedisPool jedisPool = null; private JedisConnectionUtils(){}; private static JedisPool getJedisPool () { if(jedisPool==null){ synchronized(JedisConnectionUtils.class){ if(jedisPool==null){ //1 創建連接池配置對象 JedisPoolConfig config = new JedisPoolConfig(); //2 進行配置-四個配置 config.setMaxIdle(3);//最小連接(空閑最大連接) config.setMaxTotal(10);//最大連接數 config.setMaxWaitMillis(2 * 1000);//最大等待時間 config.setTestOnBorrow(true);//獲取連接時測試連接是否暢通 //3 通過配置對象創建連接池對象 jedisPool = new JedisPool(config, "192.168.36.130", 6379, 2 * 1000, "123456"); } } } return jedisPool; } //獲取連接 public static Jedis getResource() { return getJedisPool ().getResource(); } //釋放連接 public static void closeResource(Jedis jedis) { if (jedis != null) { jedis.close(); } } }
String(字符串)
String是簡單的 key-value 鍵值對,value 不僅可以是 String,也可以是數字。String在redis內部存儲默認就是一個字符串,被redisObject所引用,當遇到incr,decr等操作時會轉成數值型進行計算,此時redisObject的encoding字段為int。
應用場景
String是最常用的一種數據類型,普通的key/value存儲都可以歸為此類,這里就不所做解釋了。
Jedis的代碼示例:
/** * exists: 判斷 K 是否存在 * set: 設置 K 與 V 的值 * get: 通過 K 獲取 V 的值 * keys: 獲取所有的 K * expire: 設置 KV 鍵值對的過期時間 * ttl: 獲取 KV 鍵值對 剩余過期時間 * @throws Exception */ @Test//key public void keyValueTest() throws Exception { Jedis jedis = JedisConnectionUtils.getResource(); //獲取連接 System.out.println("清空數據:" + jedis.flushAll()); //清空所有數據 //執行的操作 System.out.println("key為name是否存在值:" + jedis.exists("name"));//false System.out.println("key為age是否存在值:" + jedis.exists("age"));//false System.out.println("插入key為name的值:" + jedis.set("name", "武大郎")); System.out.println("插入key為age的值:" + jedis.set("age", "26")); System.out.println("再次判斷key為name是否存在值:" + jedis.exists("name"));//true System.out.println("再次判斷key為age是否存在值:" + jedis.exists("age"));//true System.out.println("獲取key為name的值:" + jedis.get("name"));//武大郎 System.out.println("獲取key為age的值:" + jedis.get("age"));//26 jedis.append("name", "燒餅");//向后追加值 System.out.println("追加后獲取key為name的值:" + jedis.get("name"));//武大郎燒餅 System.out.println("刪除key為name的值:" + jedis.del("name"));//刪除值 System.out.println("刪除后判斷key為name是否存在值:" + jedis.exists("name"));//false System.out.println("獲取所有的key:"); //name age jedis.keys("*").stream().forEach(System.out::println); System.out.println("設置key為age的過期時間:10秒"); jedis.expire("age", 10);//設置過期時間 System.out.println("睡眠阻塞:5秒"); Thread.sleep(5000); System.out.println("獲取key為age剩余過期時間:"+jedis.ttl("age"));//獲取剩余過期時間 JedisConnectionUtils.closeResource(jedis); //釋放連接 }
Redis關於String類型的常見命令如下表:
序號 | 命令 | 說明 |
---|---|---|
1 | SET key value | 此命令設置指定鍵的值。 |
2 | GET key | 獲取指定鍵的值。 |
3 | GETRANGE key start end | 獲取存儲在鍵上的字符串的子字符串。 |
4 | GETSET key value | 設置鍵的字符串值並返回其舊值。 |
5 | GETBIT key offset | 返回在鍵處存儲的字符串值中偏移處的位值 |
6 | MGET key1 [key2..] | 獲取所有給定鍵的值 |
7 | SETBIT key offset value | 存儲在鍵上的字符串值中設置或清除偏移處的位 |
8 | SETEX key seconds value | 使用鍵和到期時間來設置值 |
9 | SETNX key value | 設置鍵的值,僅當鍵不存在時 |
10 | SETRANGE key offset value | 在指定偏移處開始的鍵處覆蓋字符串的一部分 |
11 | STRLEN key | 獲取存儲在鍵中的值的長度 |
12 | MSET key value [key value …] | 為多個鍵分別設置它們的值 |
13 | MSETNX key value [key value …] | 為多個鍵分別設置它們的值,僅當鍵不存在時 |
14 | PSETEX key milliseconds value | 設置鍵的值和到期時間(以毫秒為單位) |
15 | INCR key | 將鍵的整數值增加1 |
16 | INCRBY key increment | 將鍵的整數值按給定的數值增加 |
17 | INCRBYFLOAT key increment | 將鍵的浮點值按給定的數值增加 |
18 | DECR key | 將鍵的整數值減1 |
19 | DECRBY key decrement | 按給定數值減少鍵的整數值 |
20 | APPEND key value | 將指定值附加到鍵 |
List(列表)
Redis列表是簡單的字符串列表,按插入順序排序,可重復的數據,簡單的說就是一個鏈表或者說是一個隊列。可以從頭部或尾部向Redis列表添加元素。列表的最大長度為2^32 - 1,也即每個列表支持超過40億個元素。
Redis List的實現為一個雙向鏈表,即可以支持反向查找和遍歷,更方便操作,不過帶來了部分額外的內存開銷,Redis內部的很多實現,包括發送緩沖隊列等也都是用的這個數據結構。
應用場景
Redis List的應用場景非常多,也是Redis最重要的數據結構之一,比如twitter的關注列表、粉絲列表等都可以用Redis的list結構來實現,再比如有的應用使用Redis的list類型實現一個簡單的輕量級消息隊列,生產者push,消費者pop/bpop。
Jedis的代碼示例:
@Test //List public void listTest() { Jedis jedis = JedisConnectionUtils.getResource(); System.out.println("清空數據:" + jedis.flushAll()); jedis.lpush("nameList","武大郎","張三","李四","王五","燦燦","朱雲","程印","程印"); assert 8==jedis.llen("nameList"); jedis.lrange("nameList",0,-1).stream().forEach(System.out::println); //從第一個到最后一個,負數代表倒數第幾個 assert "武大郎".equals(jedis.rpop("nameList"));//從尾部取出一個元素 assert 7==jedis.llen("nameList"); System.out.println("------------------------------------------------"); jedis.lrem("nameList",2,"程印");//刪除從左數2兩個"程印"元素 jedis.lrem("nameList",0,"張三"); //0表示刪除全部"張三"元素 assert "朱雲".equals(jedis.lpop("nameList"));//從頭部加入一個元素 jedis.lrange("nameList",0,-1).stream().forEach(System.out::println); //從第一個到最后一個,負數代表倒數第幾個 jedis.del("nameList");//清空nameList JedisConnectionUtils.closeResource(jedis); //釋放連接 }
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 | 修剪列表的指定范圍 |
14 | RPOP key | 刪除並獲取列表中的最后一個元素 |
15 | RPOPLPUSH source destination | 刪除列表中的最后一個元素,將其附加到另一個列表並返回 |
16 | RPUSH key value1 [value2] | 將一個或多個值附加到列表 |
17 | RPUSHX key value | 僅當列表存在時才將值附加到列表 |
Set(集合)
Redis的Set是string類型的無序集合。集合成員是唯一的,這就意味着集合中不能出現重復的數據。Redis 中 集合是通過哈希表實現的,所以添加,刪除,查找的復雜度都是O(1)。
集合中最大的成員數為 232 - 1 (4294967295, 每個集合可存儲40多億個成員)。
Jedis的代碼示例:
@Test public void setTest(){ Jedis jedis = JedisConnectionUtils.getResource(); System.out.println("清空數據:" + jedis.flushAll()); String nameSet = "nameSet"; jedis.sadd(nameSet,"武大郎","張三","李四","王五","燦燦","朱雲","程印","索隆"); // 游標初始值為0 String cursor = ScanParams.SCAN_POINTER_START; ScanParams scanParams = new ScanParams(); // scanParams.match(nameSet);// 匹配以 test:xttblog:* 為前綴的 key //scanParams.count(7); jedis.sscan(nameSet,cursor,scanParams).getResult().stream().forEach(System.out::println); assert 8 == jedis.scard(nameSet); //獲得元素個數 jedis.sadd(nameSet,"程印");//添加重復的元素將失效 assert 8 == jedis.scard(nameSet); String s= jedis.srandmember(nameSet);//隨機獲取一個元素 assert jedis.sismember(nameSet,s);//是否為集合成員 String nameSet2 = "nameSet2"; jedis.sadd(nameSet2,"武大郎","張三","李四","王五","燦燦","朱雲","小程印"); System.out.println("------------------------------------------------"+jedis.sdiff(nameSet,nameSet2).size()); jedis.sscan(nameSet2,cursor,scanParams).getResult().stream().forEach(System.out::println); assert jedis.sdiff(nameSet,nameSet2).size() == 2;// (nameSet-nameSet2)元素 assert jedis.sinter(nameSet,nameSet2).size() == 6;//交集 assert jedis.sunion(nameSet,nameSet2).size() == 9;//並集 jedis.del(nameSet,nameSet2); jedis.close(); }
Redis中關於Set的命令如下表:
序號 | 命令 | 說明 |
---|---|---|
1 | SADD key member1 [member2] | 將一個或多個成員添加到集合 |
2 | SCARD key | 獲取集合中的成員數 |
3 | SDIFF key1 [key2] | 減去多個集合 |
4 | SDIFFSTORE destination key1 [key2] | 減去多個集並將結果集存儲在鍵中 |
5 | SINTER key1 [key2] | 相交多個集合 |
6 | SINTERSTORE destination key1 [key2] | 交叉多個集合並將結果集存儲在鍵中 |
7 | SISMEMBER key member | 判斷確定給定值是否是集合的成員 |
8 | SMOVE source destination member | 將成員從一個集合移動到另一個集合 |
9 | SPOP key | 從集合中刪除並返回隨機成員 |
10 | SRANDMEMBER key [count] | 從集合中獲取一個或多個隨機成員 |
11 | SREM key member1 [member2] | 從集合中刪除一個或多個成員 |
12 | SUNION key1 [key2] | 添加多個集合 |
13 | SUNIONSTORE destination key1 [key2] | 添加多個集並將結果集存儲在鍵中 |
14 | SSCAN key cursor [MATCH pattern] [COUNT count] | 遞增地迭代集合中的元素 |
Hash(字典)
Redis Hash對應Value內部實際就是一個HashMap,實際這里會有2種不同實現,這個Hash的成員比較少時Redis為了節省內存會采用類似一維數組的方式來緊湊存儲,而不會采用真正的HashMap結構,對應的value redisObject的encoding為zipmap,當成員數量增大時會自動轉成真正的HashMap,此時encoding為ht。
Jedis的代碼示例:
@Test public void hashTest(){ Jedis jedis = JedisConnectionUtils.getResource(); System.out.println("清空數據:" + jedis.flushAll()); String hashKey = "user"; //hset設置一個鍵值對 jedis.hset(hashKey,"name","武大郎"); HashMap<String, String> map = new HashMap<>(); map.put("age","26"); map.put("sex","男"); //設置多個鍵值對 jedis.hmset(hashKey,map); //獲得鍵值對的個數 Long hlen = jedis.hlen(hashKey); System.out.println("Hash Size in redis:: "+hlen); assert hlen==3; System.out.println("得到全部鍵值對"+jedis.hgetAll(hashKey)); //得到全部鍵值對 List<String> user = jedis.hmget(hashKey,"name","age");//得到部分Value值 System.out.println("Stored string in redis:: "+ user); assert user.get(0).equals("武大郎"); //刪除鍵值 jedis.del(hashKey); jedis.close(); }
Redis關於Hash類型的常見命令如下表:
序號 | 命令 | 說明 |
---|---|---|
1 | HDEL key field2 [field2] | 刪除一個或多個哈希字段。 |
2 | HEXISTS key field | 判斷是否存在散列字段。 |
3 | HGET key field | 獲取存儲在指定鍵的哈希字段的值。 |
4 | HGETALL key | 獲取存儲在指定鍵的哈希中的所有字段和值 |
5 | HINCRBY key field increment | 將哈希字段的整數值按給定數字增加 |
6 | HINCRBYFLOAT key field increment | 將哈希字段的浮點值按給定數值增加 |
7 | HKEYS key | 獲取哈希中的所有字段 |
8 | HLEN key | 獲取散列中的字段數量 |
9 | HMGET key field1 [field2] | 獲取所有給定哈希字段的值 |
10 | HMSET key field1 value1 [field2 value2 ] | 為多個哈希字段分別設置它們的值 |
11 | HSET key field value | 設置散列字段的字符串值 |
12 | HSETNX key field value | 僅當字段不存在時,才設置散列字段的值 |
13 | HVALS key | 獲取哈希中的所有值 |
Sorted Set(有序集合)
Redis 有序集合和集合一樣也是string類型元素的集合,且不允許重復的成員。不同的是每個元素都會關聯一個double類型的分數。redis正是通過分數來為集合中的成員進行從小到大的排序。
有序集合的成員是唯一的,但分數(score)卻可以重復。
集合是通過哈希表實現的,所以添加,刪除,查找的復雜度都是O(1)。 集合中最大的成員數為 232 - 1 (4294967295, 每個集合可存儲40多億個成員)。
Sorted-Set的使用場景:
- 大型在線游戲的積分排名;
- 構建索引數據;
Jedis的代碼示例:
序號 | 命令 | 說明 |
---|---|---|
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的特性
多數據
提供16個數據庫(0-15),默認為0號數據庫,可是通過select index
選擇。
事務
和關系型數據庫一樣,Redis也提供事務性操作:
- DISCARD 丟棄在MULTI之后發出的所有命令(放棄事務,回滾)
- EXEC 執行MULTI后發出的所有命令(提交事務)
- MULTI 標記事務塊的開始(開始事務)
- UNWATCH 取消 WATCH 命令對所有 key 的監視。
- WATCH key [key …] 監視給定的鍵以確定MULTI / EXEC塊的執行
Redis中示例代碼如下:
@Test public void transactionTest(){ Jedis jedis = JedisConnectionUtils.getResource(); System.out.println("清空數據:" + jedis.flushAll()); jedis.select(1);//提供16個數據庫(0-15),默認為0號數據庫,可是通過select index選擇。 Transaction transaction = jedis.multi();//開啟事務 transaction.set("name", "武大郎"); System.out.println(transaction.get("name")); transaction.exec();//提交事務 System.out.println(jedis.get("name")); transaction = jedis.multi();//開啟事務 transaction.set("name", "武大郎燒餅"); System.out.println(transaction.get("name")); transaction.discard();//撤銷事務 System.out.println(jedis.get("name")); jedis.close(); }