Redis(3)-----初識Redis-----基礎redis+java程式碼
阿新 • • 發佈:2018-11-12
一,連結redis
static Jedis jedis = new Jedis("127.0.01"); /** * https://blog.csdn.net/z23546498/article/details/73556260 測試連結 */ @Test public void getJedis() { jedis.set("hello", "world"); String output = jedis.get("hello"); System.out.println(output); }
二,String型別
/** * 1,redis操作字串 * * @throws InterruptedException */ @Test public void testString() throws InterruptedException { jedis.select(1); jedis.set("testString", "123"); // 往redis中放入字串 System.out.println("1-----從redis中獲取剛剛放進去的testString:" + jedis.get("testString")); jedis.incr("testString"); // 自增,不存在testInt則自增結果是1,如果不是字串,自增會報JedisDataException System.out.println("2-----從redis中獲取自增後的testString:" + jedis.get("testString")); jedis.decr("testString"); // 自減,效果同自增 System.out.println("3-----從redis中獲取自減後的testString:" + jedis.get("testString")); // incrby方法可以自定要增加多少 jedis.append("testString", "456abcd"); // 在後面追加 System.out.println("4-----從redis中獲取追加後的testString:" + jedis.get("testString")); String sub = jedis.substr("testString", 2, 6); // 切割字串 System.out.println("5-----substr方法的返回值:" + sub); System.out.println("6-----從redis中獲取切割後的testString:" + jedis.get("testString")); // 可以看出,substr方法並不會破壞原有值,只是取出來加工而已 jedis.rename("testString", "newString"); // 欄位改名,值不會變 System.out.println("7-----testString改名成newString後,值為:" + jedis.get("newString")); String type = jedis.type("newString");// 獲取其資料型別 System.out.println("8-----newString的資料型別是:" + type); long length = jedis.strlen("newString"); // 獲取字串長度 System.out.println("9-----newString的字串長度為:" + length); jedis.set("testString6", "哈哈"); jedis.set("testString7", "呵呵"); jedis.set("testString8", "helloword"); jedis.set("testString99", "SMSP"); Set<String> keys = jedis.keys("*"); // 獲取所有符合條件的鍵 System.out.println("10-----返回redis中所有的鍵:" + keys); keys = jedis.keys("*String?"); System.out.println("11-----返回redis中所有正則符合*String?的鍵:" + keys); jedis.del("testString"); // 字串刪除 System.out.println("12-----從redis刪除testInt後,testInt是否還存在:" + jedis.exists("testString")); System.out.println("12-----從redis刪除testInt後,testInt是否還存在:" + jedis.exists("testString99")); jedis.set("testString2", "你好啊!!!"); jedis.expire("testString2", 2); // 設定有效期,單位是秒 System.out.println("13-----從redis中獲取testString2的值為:" + jedis.get("testString2")); Thread.sleep(3000); System.out.println("14-----3秒後從redis中獲取testString2的值為:" + jedis.get("testString2")); // 過期了,會找不到該欄位,返回null // ttl方法可以返回剩餘有效時間,expire如果方法不指定時間,就是將該欄位有效期設為無限 }
1-----從redis中獲取剛剛放進去的testString:123 2-----從redis中獲取自增後的testString:124 3-----從redis中獲取自減後的testString:123 4-----從redis中獲取追加後的testString:123456abcd 5-----substr方法的返回值:3456a 6-----從redis中獲取切割後的testString:123456abcd 7-----testString改名成newString後,值為:123456abcd 8-----newString的資料型別是:string 9-----newString的字串長度為:10 10-----返回redis中所有的鍵:[testString99, testString6, testString7, testString8, newString] 11-----返回redis中所有正則符合*String?的鍵:[testString7, testString8, testString6] 12-----從redis刪除testInt後,testInt是否還存在:false 12-----從redis刪除testInt後,testInt是否還存在:true 13-----從redis中獲取testString2的值為:你好啊!!! 14-----3秒後從redis中獲取testString2的值為:null
三,list類的基本操作,有序可重複
@Test public void list() { jedis.select(2); // 列表的插入與獲取(可以重複) jedis.lpush("testList", "Redis"); // 從左邊插入 jedis.lpush("testList", "Mongodb"); jedis.lpush("testList", "Mysql"); jedis.lpush("testList", "Mysql"); jedis.rpush("testList", "DB2"); // 從右邊插入 List<String> list = jedis.lrange("testList", 0, -1); // 從左到右遍歷,3個引數分別是,key,開始位置,結束位置(-1代表到最後) for (int i = 0; i < list.size(); i++) { System.out.printf("從redis中獲取剛剛放進去的testList[%d]: %s\n", i, list.get(i)); } System.out.println(); String lpop = jedis.lpop("testList"); // 刪掉最左邊的那個 String rpop = jedis.rpop("testList"); // 刪掉最右邊的那個 System.out.printf("被刪的左邊元素是:%s,被刪的右邊元素是:%s\n", lpop, rpop); list = jedis.lrange("testList", 0, -1); for (int i = 0; i < list.size(); i++) { System.out.printf("從redis中獲取被刪除後的testList[%d]: %s\n", i, list.get(i)); } System.out.println(); jedis.ltrim("testList", 1, 2); // 裁剪列表,三個引數分別是,key,開始位置,結束位置 list = jedis.lrange("testList", 0, -1); for (int i = 0; i < list.size(); i++) { System.out.printf("從redis中獲取被裁剪後的testList[%d]: %s\n", i, list.get(i)); } jedis.del("testList"); // 刪除列表 System.out.println("從redis刪除testList後,testList是否還存在:" + jedis.exists("testList")); }
從redis中獲取剛剛放進去的testList[0]: Mysql 從redis中獲取剛剛放進去的testList[1]: Mysql 從redis中獲取剛剛放進去的testList[2]: Mongodb 從redis中獲取剛剛放進去的testList[3]: Redis 從redis中獲取剛剛放進去的testList[4]: DB2 被刪的左邊元素是:Mysql,被刪的右邊元素是:DB2 從redis中獲取被刪除後的testList[0]: Mysql 從redis中獲取被刪除後的testList[1]: Mongodb 從redis中獲取被刪除後的testList[2]: Redis 從redis中獲取被裁剪後的testList[0]: Mongodb 從redis中獲取被裁剪後的testList[1]: Redis 從redis刪除testList後,testList是否還存在:false
三,集合型別的基本操作,無序不重複
/** * * 3.1,集合型別的基本操作,無序不重複 */ @Test public void set() { jedis.sadd("testSet", "lida", "wch", "chf", "lxl", "wch"); // 新增元素,不可重複 Set<String> set = jedis.smembers("testSet"); // 獲取集合中的全部元素 System.out.println("從testSet中獲取的元素:" + set); long length = jedis.scard("testSet"); // 求集合的長度 System.out.println("\n獲取testSet的長度:" + length); System.out.println(); jedis.srem("testSet", "wch"); // 從testSet移除wch set = jedis.smembers("testSet"); System.out.println("從testSet中獲取移除後的的元素:" + set); System.out.println(); boolean exist = jedis.sismember("testSet", "lida"); // 判斷元素是否包含在該集合中 System.out.println("檢查lida是否包含在testSet中:" + exist); System.out.println(); String spop = jedis.spop("testSet");// 隨機的移除spop中的一個元素,並返回它 System.out.println("testSet中被隨機移除的元素是:" + spop); System.out.println(); jedis.del("testSet"); // 刪除整個集合 System.out.println("刪除後,testSet是否還是存在:" + jedis.exists("testSet")); System.out.println(); System.out.println(); }
從testSet中獲取的元素:[chf, lxl, lida, wch] 獲取testSet的長度:4 從testSet中獲取移除後的的元素:[chf, lxl, lida] 檢查lida是否包含在testSet中:true testSet中被隨機移除的元素是:lida 刪除後,testSet是否還是存在:false
補充:集合之間的運算,交集、並集、差集
@Test public void sets() { jedis.sadd("set1", "a", "b", "c", "d"); jedis.sadd("set2", "b", "c", "e"); Set<String> set = jedis.sdiff("set1", "set2"); // 求兩個集合的差集(只會返回存在於1,但2不存在的) System.out.println("求出兩個集合之間的差集:" + set); // 會輸出a和d // 還有一個sdiffstore的api,可以把sdiff的計算結果賦值到另一個set中,下面的交集和並集也類似 System.out.println(); set = jedis.sinter("set1", "set2"); // 求兩個集合的交集 System.out.println("求出兩個集合之間的交集:" + set); // 會輸出b和c System.out.println(); set = jedis.sunion("set1", "set2"); // 求兩個集合的並集 System.out.println("求出兩個集合之間的並集:" + set); }
求出兩個集合之間的差集:[d, a]
求出兩個集合之間的交集:[b, c]
求出兩個集合之間的並集:[a, b, c, d, e]
四,雜湊的基本操作,鍵值對裡面還有鍵值對,經常用來儲存多個欄位資訊,也可以理解為存放一個map,雜湊是redis的儲存原型
@Test public void hash() { Map<String, String> map = new HashMap<String, String>(); map.put("k1", "v1"); map.put("k2", "v2"); map.put("k3", "v3"); map.put("k4", "123"); jedis.hmset("hash1", map); // 存放一個雜湊 Map<String, String> getMap = jedis.hgetAll("hash1"); // 從redis中取回來 System.out.println("從redis中取回的hash1雜湊:" + getMap.toString()); System.out.println(); List<String> hmget = jedis.hmget("hash1", "k1", "k3"); // 從雜湊中取回一個或多個欄位資訊 System.out.println("從hash1雜湊中兩個欄位來看看:" + hmget); System.out.println(); jedis.hdel("hash1", "k1"); // 刪除雜湊中的一個或者多個欄位 getMap = jedis.hgetAll("hash1"); System.out.println("從redis中取回的被刪除後的hash1雜湊:" + getMap); System.out.println(); long length = jedis.hlen("hash1"); // 求出集合的長度 System.out.println("雜湊hash1的長度為:" + length); System.out.println(); boolean exists = jedis.hexists("hash1", "k5"); // 判斷某個欄位是否存在於雜湊中 System.out.println("k5欄位是否存在於雜湊中:" + exists); System.out.println(); Set<String> keys = jedis.hkeys("hash1"); // 獲取雜湊的所有欄位名 System.out.println("hash1的所有欄位名:" + keys); System.out.println(); List<String> values = jedis.hvals("hash1"); // 獲取雜湊的所有欄位值,實質的方法實現,是用上面的hkeys後再用hmget System.out.println("hash1的所有欄位值:" + values); System.out.println(); jedis.hincrBy("hash1", "k4", 10); // 給雜湊的某個欄位進行加法運算 System.out.println("執行加法執行後的hash1雜湊:" + jedis.hgetAll("hash1")); System.out.println(); jedis.del("hash1"); // 刪除雜湊 System.out.println("刪除hash1後,hash1是否還存在redis中:" + jedis.exists("hash1")); }
從redis中取回的hash1雜湊:{k1=v1, k2=v2, k3=v3, k4=123} 從hash1雜湊中兩個欄位來看看:[v1, v3] 從redis中取回的被刪除後的hash1雜湊:{k2=v2, k3=v3, k4=123} 雜湊hash1的長度為:3 k5欄位是否存在於雜湊中:false hash1的所有欄位名:[k3, k4, k2] hash1的所有欄位值:[v3, v2, 123] 執行加法執行後的hash1雜湊:{k2=v2, k3=v3, k4=133} 刪除hash1後,hash1是否還存在redis中:false
五,有序集合的基本使用,zset是set的升級版,在無序的基礎上,加入了一個權重,使其有序化<br/>另一種理解,zset是hash的特殊版,一樣的存放一些鍵值對,但這裡的值只能是數字,不能是字串<br/>zset廣泛應用於排名類的場景
@Test public void zset() { Map<String, Double> map = new HashMap<String, Double>(); map.put("第二名", 24.3); // 這裡以小組成員的年齡來演示 map.put("第一名", 30.0); map.put("第三名", 23.5); map.put("第四名", 22.1); map.put("第二名", 24.3); // 這個不會被加入,應該重複了 jedis.zadd("zset1", map); // 新增一個zset Set<String> range = jedis.zrange("zset1", 0, -1); // 從小到大排序,返回所有成員,三個引數:鍵、開始位置、結束位置(-1代表全部) // zrange方法還有很多衍生的方法,如zrangeByScore等,只是多了一些引數和篩選範圍而已,比較簡單,自己看看api就知道了 System.out.println("zset返回的所有從小大到排序的成員:" + range); System.out.println(""); Set<String> revrange = jedis.zrevrange("zset1", 0, -1); // 從大到小排序,類似上面的range System.out.println("zset返回的所有排序的成員:" + revrange); System.out.println(""); long length = jedis.zcard("zset1"); // 求有效長度 System.out.println("zset1的長度:" + length); System.out.println(); long zcount = jedis.zcount("zset1", 22.1, 30.0); // 求出zset中,兩個成員的排名之差,注意不是求長度, System.out.println("zset1中,22.1和30.0差了" + zcount + "名"); System.out.println(); long zrank = jedis.zrank("zset1", "第四名"); // 求出zset中某成員的排位,注意第一是從0開始的 System.out.println("第四名在zset1中排名:" + zrank); System.out.println(); double zscore = jedis.zscore("zset1", "第二名"); // 獲取zset中某成員的值 System.out.println("zset1中第二名的值為:" + zscore); System.out.println(); jedis.zincrby("zset1", 10, "第三名"); // 給zset中的某成員做加法運算 System.out.println("zset1中第三名加10後,排名情況為:" + jedis.zrange("zset1", 0, -1)); System.out.println(); jedis.zrem("zset1", "第四名"); // 刪除zset中某個成員 // zrem還有衍生的zremByScore和zremByRank,分別是刪除某個分數區間和排名區間的成員 System.out.println("zset1刪除第四名後,剩下:" + jedis.zrange("zset1", 0, -1)); System.out.println(); }
zset返回的所有從小大到排序的成員:[第四名, 第三名, 第二名, 第一名] zset返回的所有排序的成員:[第一名, 第二名, 第三名, 第四名] zset1的長度:4 zset1中,22.1和30.0差了4名 第四名在zset1中排名:0 zset1中第二名的值為:24.3 zset1中第三名加10後,排名情況為:[第四名, 第二名, 第一名, 第三名] zset1刪除第四名後,剩下:[第二名, 第一名, 第三名]
補充: 有序集合的運算,交集、並集(最小、最大、總和)
@Test public void zsets() { Map<String, Double> map1 = new HashMap<String, Double>(); map1.put("a", 24.3); // 這裡以小組成員的年齡來演示 map1.put("b", 30.0); map1.put("c", 23.5); map1.put("d", 22.1); Map<String, Double> map2 = new HashMap<String, Double>(); map2.put("a", 24.3); map2.put("b", 29.6); map2.put("c", 23.5); map2.put("d", 21.3); jedis.zadd("zset1", map1); jedis.zadd("zset2", map2); System.out.println("zset1的值有:" + jedis.zrangeWithScores("zset1", 0, -1)); System.out.println("zset2的值有:" + jedis.zrangeWithScores("zset2", 0, -1)); System.out.println(); jedis.zinterstore("zset_inter", "zset1", "zset2"); // 把兩個集合進行交集運算,運算結果賦值到zset_inter中 System.out.println("看看兩個zset交集運算結果:" + jedis.zrangeWithScores("zset_inter", 0, -1)); jedis.zinterstore ("zset_union", "zset1", "zset2");// 把兩個集合進行並集運算,運算結果賦值到zset_union中 System.out.println("看看兩個zset並集運算結果:" + jedis.zrangeWithScores("zset_union", 0, -1)); System.out.println("可以看出,zset的交集和並集計算,預設會把兩個zset的score相加"); ZParams zParams = new ZParams(); zParams.aggregate(ZParams.Aggregate.MAX); jedis.zinterstore("zset_inter", zParams, "zset1", "zset2"); // 通過指定ZParams來設定集合運算的score處理,有MAX MIN // SUM三個可以選擇,預設是SUM System.out.println("看看兩個zset交集max運算結果:" + jedis.zrangeWithScores("zset_inter", 0, -1)); }
zset1的值有:[[[100],22.1], [[99],23.5], [[97],24.3], [[98],30.0]] zset2的值有:[[[100],21.3], [[99],23.5], [[97],24.3], [[98],29.6]] 看看兩個zset交集運算結果:[[[100],43.400000000000006], [[99],47.0], [[97],48.6], [[98],59.6]] 看看兩個zset並集運算結果:[[[100],43.400000000000006], [[99],47.0], [[97],48.6], [[98],59.6]] 可以看出,zset的交集和並集計算,預設會把兩個zset的score相加 看看兩個zset交集max運算結果:[[[100],22.1], [[99],23.5], [[97],24.3], [[98],30.0]]
六,釋出訂閱模式
監視著
package com.redis; import redis.clients.jedis.JedisPubSub; public class RedisMsgPubSubListener extends JedisPubSub { @Override public void onMessage(String channel, String message) { System.out.println("channel:" + channel + "receives message :" + message); //this.unsubscribe();//取消訂閱 } @Override public void onSubscribe(String channel, int subscribedChannels) { System.out.println("channel:" + channel + "is been subscribed:" + subscribedChannels); } @Override public void onUnsubscribe(String channel, int subscribedChannels) { System.out.println("channel:" + channel + "is been unsubscribed:" + subscribedChannels); } @Override public void onPMessage(String s, String s1, String s2) { // TODO Auto-generated method stub } @Override public void onPUnsubscribe(String s, int i) { // TODO Auto-generated method stub } @Override public void onPSubscribe(String s, int i) { // TODO Auto-generated method stub } }
釋出者:
package com.redis; import redis.clients.jedis.Jedis; public class TestPublish { public static void main(String[] args) throws Exception { final Jedis jedis = new Jedis("localhost"); new Thread() { public void run() { try { for (int i = 0; i < 10; i++) { jedis.publish("redisChat", "要傳送的訊息內容" + i); // 每隔一秒推送一條訊息 System.out.printf("成功向redisChat推送訊息:%s\n", i); Thread.sleep(1000); } } catch (Exception e) { e.printStackTrace(); } }; }.start(); /* * jedis.publish("redisChat", "Redis is a great caching technique"); Thread.sleep(5000); * jedis.publish("redisChat", "build your dream"); Thread.sleep(5000); jedis.publish("redisChat", "over"); */ } }
訂閱者:
package com.redis; import redis.clients.jedis.Jedis; public class TestSubscribe { public static void main(String[] args){ Jedis jedis = new Jedis("localhost"); RedisMsgPubSubListener listener = new RedisMsgPubSubListener(); /** * 注意:subscribe是一個阻塞的方法,在取消訂閱該頻道前,會一直阻塞在這,只有當取消了訂閱才會執行下面的other code, * 參考上面程式碼,我在onMessage裡面收到訊息後,呼叫了this.unsubscribe(); 來取消訂閱,這樣才會執行後面的other code */ jedis.subscribe(listener, "redisChat"); //如果沒有取消訂閱,方法將一直堵塞在此處不會向下執行 //to do others } }
先啟動訂閱者,再啟動釋出者,控制檯列印
釋出者控制檯:
成功向redisChat推送訊息:0 成功向redisChat推送訊息:1 成功向redisChat推送訊息:2 成功向redisChat推送訊息:3 成功向redisChat推送訊息:4 成功向redisChat推送訊息:5 成功向redisChat推送訊息:6 成功向redisChat推送訊息:7 成功向redisChat推送訊息:8 成功向redisChat推送訊息:9
訂閱者控制檯:
channel:redisChatis been subscribed:1 channel:redisChatreceives message :要傳送的訊息內容0 channel:redisChatreceives message :要傳送的訊息內容1 channel:redisChatreceives message :要傳送的訊息內容2 channel:redisChatreceives message :要傳送的訊息內容3 channel:redisChatreceives message :要傳送的訊息內容4 channel:redisChatreceives message :要傳送的訊息內容5 channel:redisChatreceives message :要傳送的訊息內容6 channel:redisChatreceives message :要傳送的訊息內容7 channel:redisChatreceives message :要傳送的訊息內容8 channel:redisChatreceives message :要傳送的訊息內容9
kk