Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。从2010年3月15日起,Redis的开发工作由VMware主持。从2013年5月开始,Redis的开发由Pivotal赞助。

 这里就不将redis是怎么安装和配置的了,大家自行在CSDN的其他博客看看,这个博客主要分享的是,Java使用jedis库去操作redis。本篇涉及了redis的5种基本数据类型的最基本操作:string、list、set、hash、zset,以及简单的redis消息队列的使用。

  jedis是官方推荐的,使用java操作redis的类库,目前官网的最新稳定版是2.9,推荐大家使用maven或者gradle去构建项目,maven所需的jedis的依赖如下

  1. <dependency>  
  2.     <groupId>redis.clients</groupId>  
  3.     <artifactId>jedis</artifactId>  
  4.     <version>2.9.0</version>  
  5. </dependency>  

   

  其实这个依赖只有3个jar包,jedis-2.9.0.jar,commons-pool-1.6.jar,commons-pool2-2.4.2.jar,后面的两个common的pool包,是配置jedis的连接池用的,如果不想使用连接池,那么只要导入jedis-2.9.0.jar就够了。

  不多说了,直接上代码吧,jedis的这些api,和redis-cli命令是一样的,所以只要熟悉redis-cli的命令,那个jedis的api就可以驾轻就熟了。


  1. import java.util.HashMap;  
  2. import java.util.List;  
  3. import java.util.Map;  
  4. import java.util.Set;  
  5.   
  6. import redis.clients.jedis.Jedis;  
  7. import redis.clients.jedis.JedisPool;  
  8. import redis.clients.jedis.JedisPoolConfig;  
  9. import redis.clients.jedis.JedisPubSub;  
  10. import redis.clients.jedis.ZParams;  
  11.   
  12. /** 
  13.  * redis常用api 
  14.  *  
  15.  * @author Kazz 
  16.  * 
  17.  */  
  18. public class RedisDemo {  
  19.   
  20.     private static JedisPool jedisPool = null;  
  21.   
  22.     public static void main(String[] args) throws Exception {  
  23.   
  24.         // 这个是最简单的redis连接示例,不过不推荐,推荐使用数据库连接池  
  25.         // Jedis jedis = new Jedis("192.168.8.128", 6379);// 连接 Redis 服务  
  26.         // jedis.auth("123456"); // 设置密码  
  27.         // System.out.println("Server is running: " + jedis.ping());//  
  28.         // 查看服务是否运行  
  29.   
  30.         init();  
  31.         string();  
  32.   
  33.         list();  
  34.           
  35.         set();  
  36.           
  37.         sets();  
  38.           
  39.         hash();  
  40.   
  41.         zset();  
  42.   
  43.         zsets();  
  44.   
  45.         publisher();  
  46.   
  47.         subscribe();  
  48.     }  
  49.   
  50.     /** 
  51.      * 初始化redis连接池 
  52.      */  
  53.     private static void init() {  
  54.         JedisPoolConfig config = new JedisPoolConfig(); // Jedis连接池  
  55.         config.setMaxIdle(8); // 最大空闲连接数  
  56.         config.setMaxTotal(8);// 最大连接数  
  57.         config.setMaxWaitMillis(1000); // 获取连接是的最大等待时间,如果超时就抛出异常  
  58.         config.setTestOnBorrow(false);// 在borrow一个jedis实例时,是否提前进行validate操作;如果为true,则得到的jedis实例均是可用的;  
  59.         config.setTestOnReturn(true);  
  60.         jedisPool = new JedisPool(config, "192.168.8.128"63795000"123456"0); // 配置、ip、端口、连接超时时间、密码、数据库编号(0~15)  
  61.     }  
  62.   
  63.     /** 
  64.      * string类型的基本操作,string是redis的最基本数据类型,很多操作都是其他数据类型能用的,如del、exists、expire 
  65.      *  
  66.      * @throws Exception 
  67.      *  
  68.      */  
  69.     private static void string() throws Exception {  
  70.         Jedis jedis = jedisPool.getResource();  
  71.         jedis.flushDB(); // 清空数据库  
  72.   
  73.         jedis.set("testString""123"); // 往redis中放入字符串  
  74.         System.out.println("从redis中获取刚刚放进去的testString:" + jedis.get("testString"));  
  75.   
  76.         jedis.incr("testString"); // 自增,不存在testInt则自增结果是1,如果不是字符串,自增会报JedisDataException  
  77.         System.out.println("从redis中获取自增后的testString:" + jedis.get("testString"));  
  78.   
  79.         jedis.decr("testString"); // 自减,效果同自增  
  80.         System.out.println("从redis中获取自减后的testString:" + jedis.get("testString"));  
  81.         // incrby方法可以自定要增加多少  
  82.   
  83.         jedis.append("testString""456abcd"); // 在后面追加  
  84.         System.out.println("从redis中获取追加后的testString:" + jedis.get("testString"));  
  85.   
  86.         String sub = jedis.substr("testString"26); // 切割字符串  
  87.         System.out.println("substr方法的返回值:" + sub);  
  88.         System.out.println("从redis中获取切割后的testString:" + jedis.get("testString")); // 可以看出,substr方法并不会破坏原有值,只是取出来加工而已  
  89.   
  90.         jedis.rename("testString""newString"); // 字段改名,值不会变  
  91.         System.out.println("testString改名成newString后,值为:" + jedis.get("newString"));  
  92.   
  93.         String type = jedis.type("newString");// 获取其数据类型  
  94.         System.out.println("newString的数据类型是:" + type);  
  95.   
  96.         long length = jedis.strlen("newString"); // 获取字符串长度  
  97.         System.out.println("newString的字符串长度为:" + length);  
  98.   
  99.         jedis.set("testString6""哈哈");  
  100.         jedis.set("testString7""呵呵");  
  101.         jedis.set("testString8""helloword");  
  102.         jedis.set("testString99""SMSP");  
  103.         Set<String> keys = jedis.keys("*"); // 获取所有符合条件的键  
  104.         System.out.println("返回redis中所有的键:" + keys);  
  105.         keys = jedis.keys("*String?");  
  106.         System.out.println("返回redis中所有正则符合*String?的键:" + keys);  
  107.   
  108.         jedis.del("testString"); // 字符串删除  
  109.         System.out.println("从redis删除testInt后,testInt是否还存在:" + jedis.exists("testString"));  
  110.         System.out.println();  
  111.   
  112.         jedis.set("testString2""你好啊!!!");  
  113.         jedis.expire("testString2"2); // 设置有效期,单位是秒  
  114.         System.out.println("从redis中获取testString2的值为:" + jedis.get("testString2"));  
  115.         Thread.sleep(3000);  
  116.         System.out.println("3秒后从redis中获取testString2的值为:" + jedis.get("testString2")); // 过期了,会找不到该字段,返回null  
  117.         // ttl方法可以返回剩余有效时间,expire如果方法不指定时间,就是将该字段有效期设为无限  
  118.         System.out.println();  
  119.         System.out.println();  
  120.         jedis.close();  
  121.     }  
  122.   
  123.     /** 
  124.      * list类的基本操作,有序可重复 
  125.      *  
  126.      */  
  127.     private static void list() {  
  128.         Jedis jedis = jedisPool.getResource();  
  129.         jedis.flushDB(); // 清空数据库  
  130.   
  131.         // 列表的插入与获取(可以重复)  
  132.         jedis.lpush("testList""Redis"); // 从左边插入  
  133.         jedis.lpush("testList""Mongodb");  
  134.         jedis.lpush("testList""Mysql");  
  135.         jedis.lpush("testList""Mysql");  
  136.         jedis.rpush("testList""DB2"); // 从右边插入  
  137.   
  138.         List<String> list = jedis.lrange("testList"0, -1); // 从左到右遍历,3个参数分别是,key,开始位置,结束位置(-1代表到最后)  
  139.         for (int i = 0; i < list.size(); i++) {  
  140.             System.out.printf("从redis中获取刚刚放进去的testList[%d]: %s\n", i, list.get(i));  
  141.         }  
  142.   
  143.         System.out.println();  
  144.         String lpop = jedis.lpop("testList"); // 删掉最左边的那个  
  145.         String rpop = jedis.rpop("testList"); // 删掉最右边的那个  
  146.         System.out.printf("被删的左边元素是:%s,被删的右边元素是:%s\n", lpop, rpop);  
  147.   
  148.         list = jedis.lrange("testList"0, -1);  
  149.         for (int i = 0; i < list.size(); i++) {  
  150.             System.out.printf("从redis中获取被删除后的testList[%d]: %s\n", i, list.get(i));  
  151.         }  
  152.   
  153.         System.out.println();  
  154.         jedis.ltrim("testList"12); // 裁剪列表,三个参数分别是,key,开始位置,结束位置  
  155.         list = jedis.lrange("testList"0, -1);  
  156.         for (int i = 0; i < list.size(); i++) {  
  157.             System.out.printf("从redis中获取被裁剪后的testList[%d]: %s\n", i, list.get(i));  
  158.         }  
  159.   
  160.         jedis.del("testList"); // 删除列表  
  161.         System.out.println("从redis删除testList后,testList是否还存在:" + jedis.exists("testList"));  
  162.         System.out.println();  
  163.         System.out.println();  
  164.         jedis.close();  
  165.     }  
  166.   
  167.     /** 
  168.      * 集合类型的基本操作,无序不重复 
  169.      */  
  170.     private static void set() {  
  171.         Jedis jedis = jedisPool.getResource();  
  172.         jedis.flushDB(); // 清空数据库  
  173.   
  174.         jedis.sadd("testSet""lida""wch""chf""lxl""wch"); // 添加元素,不可重复  
  175.   
  176.         Set<String> set = jedis.smembers("testSet"); // 获取集合中的全部元素  
  177.         System.out.println("从testSet中获取的元素:" + set);  
  178.   
  179.         long length = jedis.scard("testSet"); // 求集合的长度  
  180.         System.out.println("\n获取testSet的长度:" + length);  
  181.         System.out.println();  
  182.   
  183.         jedis.srem("testSet""wch"); // 从testSet移除wch  
  184.         set = jedis.smembers("testSet");  
  185.         System.out.println("从testSet中获取移除后的的元素:" + set);  
  186.         System.out.println();  
  187.   
  188.         boolean exist = jedis.sismember("testSet""lida"); // 判断元素是否包含在该集合中  
  189.         System.out.println("检查lida是否包含在testSet中:" + exist);  
  190.         System.out.println();  
  191.   
  192.         String spop = jedis.spop("testSet");// 随机的移除spop中的一个元素,并返回它  
  193.         System.out.println("testSet中被随机移除的元素是:" + spop);  
  194.         System.out.println();  
  195.   
  196.         jedis.del("testSet"); // 删除整个集合  
  197.         System.out.println("删除后,testSet是否还是存在:" + jedis.exists("testSet"));  
  198.         System.out.println();  
  199.         System.out.println();  
  200.   
  201.         jedis.close();  
  202.     }  
  203.   
  204.     /** 
  205.      * 集合之间的运算,交集、并集、差集 
  206.      */  
  207.     private static void sets() {  
  208.         Jedis jedis = jedisPool.getResource();  
  209.         jedis.flushDB(); // 清空数据库  
  210.         jedis.sadd("set1""a""b""c""d");  
  211.         jedis.sadd("set2""b""c""e");  
  212.   
  213.         Set<String> set = jedis.sdiff("set1""set2"); // 求两个集合的差集(只会返回存在于1,但2不存在的)  
  214.         System.out.println("求出两个集合之间的差集:" + set); // 会输出a和d  
  215.         // 还有一个sdiffstore的api,可以把sdiff的计算结果赋值到另一个set中,下面的交集和并集也类似  
  216.         System.out.println();  
  217.   
  218.         set = jedis.sinter("set1""set2"); // 求两个集合的交集  
  219.         System.out.println("求出两个集合之间的交集:" + set); // 会输出b和c  
  220.         System.out.println();  
  221.   
  222.         set = jedis.sunion("set1""set2"); // 求两个集合的并集  
  223.         System.out.println("求出两个集合之间的并集:" + set);  
  224.         System.out.println();  
  225.         System.out.println();  
  226.   
  227.         jedis.close();  
  228.     }  
  229.   
  230.     /** 
  231.      * 散列的基本操作,键值对里面还有键值对,经常用来存储多个字段信息,也可以理解为存放一个map,散列是redis的存储原型 
  232.      */  
  233.     private static void hash() {  
  234.         Jedis jedis = jedisPool.getResource();  
  235.         jedis.flushDB(); // 清空数据库  
  236.   
  237.         Map<String, String> map = new HashMap<String, String>();  
  238.         map.put("k1""v1");  
  239.         map.put("k2""v2");  
  240.         map.put("k3""v3");  
  241.         map.put("k4""123");  
  242.         jedis.hmset("hash1", map); // 存放一个散列  
  243.   
  244.         Map<String, String> getMap = jedis.hgetAll("hash1"); // 从redis中取回来  
  245.         System.out.println("从redis中取回的hash1散列:" + getMap.toString());  
  246.         System.out.println();  
  247.   
  248.         List<String> hmget = jedis.hmget("hash1""k1""k3"); // 从散列中取回一个或多个字段信息  
  249.         System.out.println("从hash1散列中两个字段来看看:" + hmget);  
  250.         System.out.println();  
  251.   
  252.         jedis.hdel("hash1""k1"); // 删除散列中的一个或者多个字段  
  253.         getMap = jedis.hgetAll("hash1");  
  254.         System.out.println("从redis中取回的被删除后的hash1散列:" + getMap);  
  255.         System.out.println();  
  256.   
  257.         long length = jedis.hlen("hash1"); // 求出集合的长度  
  258.         System.out.println("散列hash1的长度为:" + length);  
  259.         System.out.println();  
  260.   
  261.         boolean exists = jedis.hexists("hash1""k5"); // 判断某个字段是否存在于散列中  
  262.         System.out.println("k5字段是否存在于散列中:" + exists);  
  263.         System.out.println();  
  264.   
  265.         Set<String> keys = jedis.hkeys("hash1"); // 获取散列的所有字段名  
  266.         System.out.println("hash1的所有字段名:" + keys);  
  267.         System.out.println();  
  268.   
  269.         List<String> values = jedis.hvals("hash1"); // 获取散列的所有字段值,实质的方法实现,是用上面的hkeys后再用hmget  
  270.         System.out.println("hash1的所有字段值:" + values);  
  271.         System.out.println();  
  272.   
  273.         jedis.hincrBy("hash1""k4"10); // 给散列的某个字段进行加法运算  
  274.         System.out.println("执行加法运行后的hash1散列:" + jedis.hgetAll("hash1"));  
  275.         System.out.println();  
  276.   
  277.         jedis.del("hash1"); // 删除散列  
  278.         System.out.println("删除hash1后,hash1是否还存在redis中:" + jedis.exists("hash1"));  
  279.         System.out.println();  
  280.         System.out.println();  
  281.   
  282.         jedis.close();  
  283.     }  
  284.   
  285.     /** 
  286.      * 有序集合的基本使用,zset是set的升级版,在无序的基础上,加入了一个权重,使其有序化<br/> 
  287.      * 另一种理解,zset是hash的特殊版,一样的存放一些键值对,但这里的值只能是数字,不能是字符串<br/> 
  288.      * zset广泛应用于排名类的场景 
  289.      */  
  290.     private static void zset() {  
  291.         Jedis jedis = jedisPool.getResource();  
  292.         jedis.flushDB(); // 清空数据库  
  293.   
  294.         Map<String, Double> map = new HashMap<String, Double>();  
  295.         map.put("wch"24.3); // 这里以小组成员的年龄来演示  
  296.         map.put("lida"30.0);  
  297.         map.put("chf"23.5);  
  298.         map.put("lxl"22.1);  
  299.         map.put("wch"24.3); // 这个不会被加入,应该重复了  
  300.   
  301.         jedis.zadd("zset1", map); // 添加一个zset  
  302.   
  303.         Set<String> range = jedis.zrange("zset1"0, -1); // 从小到大排序,返回所有成员,三个参数:键、开始位置、结束位置(-1代表全部)  
  304.         // zrange方法还有很多衍生的方法,如zrangeByScore等,只是多了一些参数和筛选范围而已,比较简单,自己看看api就知道了  
  305.         System.out.println("zset返回的所有从小大到排序的成员:" + range);  
  306.         System.out.println("");  
  307.   
  308.         Set<String> revrange = jedis.zrevrange("zset1"0, -1); // 从大到小排序,类似上面的range  
  309.         System.out.println("zset返回的所有排序的成员:" + revrange);  
  310.         System.out.println("");  
  311.   
  312.         long length = jedis.zcard("zset1"); // 求有效长度  
  313.         System.out.println("zset1的长度:" + length);  
  314.         System.out.println();  
  315.   
  316.         long zcount = jedis.zcount("zset1"22.130.0); // 求出zset中,两个成员的排名之差,注意不是求长度,  
  317.         System.out.println("zset1中,22.1和30.0差了" + zcount + "名");  
  318.         System.out.println();  
  319.   
  320.         long zrank = jedis.zrank("zset1""wch"); // 求出zset中某成员的排位,注意第一是从0开始的  
  321.         System.out.println("wch在zset1中排名:" + zrank);  
  322.         System.out.println();  
  323.   
  324.         double zscore = jedis.zscore("zset1""lida"); // 获取zset中某成员的值  
  325.         System.out.println("zset1中lida的值为:" + zscore);  
  326.         System.out.println();  
  327.   
  328.         jedis.zincrby("zset1"10"lxl"); // 给zset中的某成员做加法运算  
  329.         System.out.println("zset1中lxl加10后,排名情况为:" + jedis.zrange("zset1"0, -1));  
  330.         System.out.println();  
  331.   
  332.         jedis.zrem("zset1""chf"); // 删除zset中某个成员  
  333.         // zrem还有衍生的zremByScore和zremByRank,分别是删除某个分数区间和排名区间的成员  
  334.         System.out.println("zset1删除chf后,剩下:" + jedis.zrange("zset1"0, -1));  
  335.         System.out.println();  
  336.   
  337.         jedis.close();  
  338.     }  
  339.   
  340.     /** 
  341.      * 有序集合的运算,交集、并集(最小、最大、总和) 
  342.      */  
  343.     private static void zsets() {  
  344.         Jedis jedis = jedisPool.getResource();  
  345.         jedis.flushDB(); // 清空数据库  
  346.   
  347.         Map<String, Double> map1 = new HashMap<String, Double>();  
  348.         map1.put("wch"24.3); // 这里以小组成员的年龄来演示  
  349.         map1.put("lida"30.0);  
  350.         map1.put("chf"23.5);  
  351.         map1.put("lxl"22.1);  
  352.   
  353.         Map<String, Double> map2 = new HashMap<String, Double>();  
  354.         map2.put("wch"24.3);  
  355.         map2.put("lly"29.6);  
  356.         map2.put("chf"23.5);  
  357.         map2.put("zjl"21.3);  
  358.   
  359.         jedis.zadd("zset1", map1);  
  360.         jedis.zadd("zset2", map2);  
  361.   
  362.         System.out.println("zset1的值有:" + jedis.zrangeWithScores("zset1"0, -1));  
  363.         System.out.println("zset2的值有:" + jedis.zrangeWithScores("zset2"0, -1));  
  364.         System.out.println();  
  365.   
  366.         jedis.zinterstore("zset_inter""zset1""zset2"); // 把两个集合进行交集运算,运算结果赋值到zset_inter中  
  367.         System.out.println("看看两个zset交集运算结果:" + jedis.zrangeWithScores("zset_inter"0, -1));  
  368.   
  369.         jedis.zunionstore("zset_union""zset1""zset2");// 把两个集合进行并集运算,运算结果赋值到zset_union中  
  370.         System.out.println("看看两个zset并集运算结果:" + jedis.zrangeWithScores("zset_union"0, -1));  
  371.         System.out.println("可以看出,zset的交集和并集计算,默认会把两个zset的score相加");  
  372.   
  373.         ZParams zParams = new ZParams();  
  374.         zParams.aggregate(ZParams.Aggregate.MAX);  
  375.         jedis.zinterstore("zset_inter", zParams, "zset1""zset2"); // 通过指定ZParams来设置集合运算的score处理,有MAX MIN SUM三个可以选择,默认是SUM  
  376.         System.out.println("看看两个zset交集max运算结果:" + jedis.zrangeWithScores("zset_inter"0, -1));  
  377.   
  378.         //zrangeWithScores返回的是一个Set<Tuple>类型,如果直接把这个集合打印出来,会把zset的key转成ascii码,看起来不直观,建议还是使用foreach之类的遍历会好看一些  
  379.           
  380.         jedis.close();  
  381.     }  
  382.   
  383.     /** 
  384.      * 发布消息,类似于mq的生产者 
  385.      */  
  386.     private static void publisher() {  
  387.   
  388.         new Thread() {  
  389.             public void run() {  
  390.                 try {  
  391.                     Thread.sleep(1000); // 休眠一下,让订阅者有充足的时间去连上  
  392.                     Jedis jedis = jedisPool.getResource();  
  393.                     jedis.flushAll();  
  394.   
  395.                     for (int i = 0; i < 10; i++) {  
  396.                         jedis.publish("channel""要发送的消息内容" + i); // 每隔一秒推送一条消息  
  397.                         System.out.printf("成功向channel推送消息:%s\n", i);  
  398.                         Thread.sleep(1000);  
  399.                     }  
  400.   
  401.                     jedis.close();  
  402.   
  403.                 } catch (Exception e) {  
  404.                     e.printStackTrace();  
  405.                 }  
  406.   
  407.             };  
  408.         }.start();  
  409.     }  
  410.   
  411.     /** 
  412.      * 订阅消息,类似与mq的消费者 
  413.      *  
  414.      */  
  415.     private static void subscribe(){  
  416.         Jedis jedis = jedisPool.getResource();  
  417.         jedis.flushAll();  
  418.         JedisListener listener = new JedisListener();  
  419.         listener.proceed(jedis.getClient(), "channel"); // 开始监听channel频道的消息  
  420.         //listener.unsubscribe(); //取消监听  
  421.         jedis.close();  
  422.     }  
  423.   
  424.     /** 
  425.      * 重写监听器的一些重要方法,JedisPubSub里面的这些回调方法都是空的,不重写就什么事都不会发生 
  426.      *  
  427.      * @author Kazz 
  428.      * 
  429.      */  
  430.     private static class JedisListener extends JedisPubSub {  
  431.   
  432.         /** 
  433.          * 收到消息后的回调 
  434.          */  
  435.         @Override  
  436.         public void onMessage(String channel, String message) {  
  437.             System.out.println("onMessage: 收到频道[" + channel + "]的消息[" + message + "]");  
  438.         }  
  439.   
  440.         @Override  
  441.         public void onPMessage(String pattern, String channel, String message) {  
  442.             System.out.println("onPMessage: channel[" + channel + "], message[" + message + "]");  
  443.         }  
  444.   
  445.         /** 
  446.          * 成功订阅频道后的回调 
  447.          */  
  448.         @Override  
  449.         public void onSubscribe(String channel, int subscribedChannels) {  
  450.             System.out  
  451.                     .println("onSubscribe: 成功订阅[" + channel + "]," + "subscribedChannels[" + subscribedChannels + "]");  
  452.         }  
  453.   
  454.         /** 
  455.          * 取消订阅频道的回调 
  456.          */  
  457.         @Override  
  458.         public void onUnsubscribe(String channel, int subscribedChannels) {  
  459.             System.out.println(  
  460.                     "onUnsubscribe: 成功取消订阅[" + channel + "], " + "subscribedChannels[" + subscribedChannels + "]");  
  461.         }  
  462.   
  463.         @Override  
  464.         public void onPUnsubscribe(String pattern, int subscribedChannels) {  
  465.             System.out.println(  
  466.                     "onPUnsubscribe: pattern[" + pattern + "]," + "subscribedChannels[" + subscribedChannels + "]");  
  467.         }  
  468.   
  469.         @Override  
  470.         public void onPSubscribe(String pattern, int subscribedChannels) {  
  471.             System.out.println(  
  472.                     "onPSubscribe: pattern[" + pattern + "], " + "subscribedChannels[" + subscribedChannels + "]");  
  473.         }  
  474.   
  475.     }  

posted on 2018-06-12 09:51  刘达人186  阅读(1402)  评论(0编辑  收藏  举报