• 9.Redis的Java客户端Jedis


    Redis的Java客户端Jedis

      Jedis所需jar包   commons-pool-1.6.jar  jedis-2.1.0.jar

    1.Jedis常用操作(jedis中的api 和 我们在 linux中使用的命令差不多)

      a)测试连通性

    1 public static void main(String[] args) {
    2         //连接虚拟机中的 redis 服务(如果是在linux 本机中,即为192.168.89.128)
    3         //注意:连接之前需要关闭linux防火墙
    4         Jedis jedis = new Jedis("192.168.89.128",6379);
    5         
    6         //查看服务是否运行,打出pong表示OK
    7         System.out.println(jedis.ping());
    8 }

      b)1+5  (一个Key  五大数据类型)

     1 //测试 对 key 和 五大数据类型的 操作API
     2 public class TestAPI {
     3     public static void main(String[] args) {
     4         
     5         //jedis中的api 和 我们在 linux中使用的命令差不多
     6         Jedis jedis = new Jedis("192.168.89.128",6379);
     7         
     8         jedis.set("k1", "v1");  //set命令
     9         jedis.set("k2", "v2");
    10         jedis.set("k3", "v3");
    11         
    12         System.out.println(jedis.get("k3"));//get命令
    13         
    14         
    15         Set<String> keysSet = jedis.keys("*");   //类似于 keys *
    16         Iterator<String> iterator = keysSet.iterator();
    17         while(iterator.hasNext()) {
    18             String key = iterator.next();
    19             System.out.println(key);
    20         }
    21         
    22         System.out.println("k1 键是否存在 :" + jedis.exists("k1"));  
    23         System.out.println("k1 键 剩余生存时间:" + jedis.ttl("k1"));    
    24         
    25         
    26     }
    27     
    28     @Test
    29     public void testString() {
    30         Jedis jedis = new Jedis("192.168.89.128",6379);
    31         //jedis.append("k1", "v1v1");
    32         //System.out.println("append后k1的值:" + jedis.get("k1"));
    33         
    34         System.out.println("k1 的value的长度:" + jedis.strlen("k1"));
    35         
    36         System.out.println("按指定下标取值:" + jedis.getrange("k1", 0, -1));
    37         //如果不存在 则赋值
    38         jedis.setnx("k1", "v1");
    39     }
    40     
    41     @Test
    42     public void testList() {
    43         Jedis jedis = new Jedis("192.168.89.128",6379);
    44         jedis.lpush("list1", "1","2","3","4","5");   //List 类型的数据的创建,按照入栈顺序放入 这个双向链表
    45         jedis.lset("list1", 0, "100");                 //将 list1 的 第一个 元素 设置为100
    46         System.out.println("list1:" + jedis.lrange("list1", 0, -1));
    47         System.out.println("lpop:" + jedis.lpop("list1"));     //弹出
    48     }
    49     
    50     @Test
    51     public void testSet() {
    52         Jedis jedis = new Jedis("192.168.89.128",6379);
    53         jedis.sadd("set1", "1","2","3","4","5","9");
    54         jedis.sadd("set2", "1","2","3","4","5","6");
    55         System.out.println(jedis.smembers("set1"));
    56         System.out.println(jedis.smembers("set2"));
    57         //差集  在第一个set里面而不在后面任何一个set里面的项
    58         System.out.println(jedis.sdiff("set1","set2"));
    59     }
    60     
    61     @Test
    62     public void testHash() {
    63         Jedis jedis = new Jedis("192.168.89.128",6379);
    64         jedis.hset("user1", "name", "xzk");
    65         jedis.hset("user1", "age", "22");
    66         
    67         Map<String,String> map = new HashMap<String, String>();
    68         
    69         //可以一次性为某个键 赋值多个 KV 键值对
    70         map.put("name", "xzk2");
    71         map.put("age", "23");
    72         jedis.hmset("user2", map);   //直接存放一个map
    73         
    74         System.out.println(jedis.hget("user1", "age"));
    75         
    76         //可以一次性取出多个 KV键值对
    77         List<String> results = jedis.hmget("user2", "name","age");
    78         System.out.println(results);
    79     }
    80     
    81     @Test
    82     public void testZSet() {
    83         Jedis jedis = new Jedis("192.168.89.128",6379);
    84         /*jedis.zadd("zset01",60,"v1");
    85         jedis.zadd("zset1",70,"v2");
    86         jedis.zadd("zset1",80,"v3");
    87         jedis.zadd("zset1",90,"v4");*/ 
    88         
    89         Map<Double, String> scoreMembers = new HashMap<Double, String>();
    90         scoreMembers.put(60d, "v1");    //key 为 score 
    91         scoreMembers.put(70d, "v2");
    92         scoreMembers.put(80d, "v3");
    93         scoreMembers.put(90d, "v4");
    94         jedis.zadd("zset1", scoreMembers );
    95         
    96         Set<String> resultSet = jedis.zrange("zset1", 0, -1);
    97         System.out.println(resultSet);
    98     }
    99 }

      c)事务提交

     1 //关于 jedis 事务的 
     2 public class TestTX {
     3     public static void main(String[] args) throws InterruptedException {
     4         boolean retValue = transMethod();
     5         System.out.println("main retValue-------: " + retValue);
     6     }
     7     
     8     
     9     /**
    10        * 通俗点讲,watch命令就是标记一个键,如果标记了一个键, 
    11        * 在提交事务前如果该键被别人修改过,那事务就会失败,这种情况通常可以在程序中
    12        * 重新再尝试一次。
    13        * 
    14        * 首先标记了键balance,然后检查  键balance是否发生了修改,修改了取消标记,
    15        * 没有被修改的话,就启动事务进行更新操作,
    16        * 如果在此期间键balance被其它人修改, 那在提交事务(执行exec)时就会报错,(但是事务失败后,只是不执行事务而已啊,这里不会报错啊) 
    17        * 程序中通常可以捕获这类错误再重新执行一次,直到成功。
    18      * @throws InterruptedException 
    19        */
    20     private static boolean transMethod() throws InterruptedException {
    21         int balance = 100;// 可用余额
    22         int debt = 0;// 欠额
    23         int amtToSubtract = 10;// 实刷额
    24         
    25         Jedis jedis = new Jedis("192.168.89.128", 6379);
    26         jedis.set("balance", ""+ balance);
    27         jedis.set("debt", "" + debt);
    28         
    29         //监听balance,如果在此期间键balance被其它人修改, 则提交的事务 不会被执行(不会报错)
    30         jedis.watch("balance");
    31         
    32         //模拟故障,在等待的时间要去修改下 balance 这个 key的值
    33         Thread.sleep(8000);
    34         
    35         //虽然不会报错,但是可以找到这类错误,让其再重新执行一次,直到成功。
    36         //检查  键balance 是否被他人修改,如果修改了,则取消标记,返回错误
    37         if(balance != Integer.parseInt(jedis.get("balance"))) {
    38             jedis.unwatch();
    39             return false;
    40         }
    41         
    42         //事务的执行
    43         Transaction transaction = jedis.multi();
    44         transaction.decrBy("balance", amtToSubtract);
    45         transaction.incrBy("debt", amtToSubtract);
    46         //transaction.discard();    取消某个事务的执行  
    47         transaction.exec();
    48         
    49         //从redis 中拿回 新的balance 和 debt
    50         balance = Integer.parseInt(jedis.get("balance"));
    51         debt = Integer.parseInt(jedis.get("debt"));
    52         
    53         System.out.println("事务执行后,balance = " + balance + "   debt = " + debt);
    54         return true;
    55     }
    56 }

    2.JedisPool

      获取Jedis实例需要从JedisPool中获取

      用完Jedis实例需要返回给JedisPool

      如果Jedis在使用过程中出错,则也需要还给JedisPool

      

     1 public class TestJedisPool {
     2     public static void main(String[] args) {
     3         //通过单例模式创建 redis 连接池
     4         JedisPool jedisPool = JedisPoolUtil.getJedisPool();
     5         Jedis jedis = null;
     6         
     7         //通过拿到连接
     8         try{
     9             jedis = jedisPool.getResource();
    10             System.out.println(jedis.get("k1"));
    11         } catch(Exception e) {
    12             e.printStackTrace();
    13         }finally {
    14             //最后将创建的 jedis 连接放回 池中
    15             JedisPoolUtil.releaseJedis(jedisPool, jedis);
    16         }
    17         
    18         
    19     }
    20 }

      JedisPool配置总结

     1 public class JedisPoolUtil {
     2     //被volatile 修饰的/*变量*/不会被本地线程缓存,对该变量的操作都是直接操作共享内存的
     3     // JUC 里面也用到了 volatile 来保证 内存可见性
     4     private static volatile JedisPool jedisPool = null;
     5 
     6     public static JedisPool getJedisPool() {
     7         if (null == jedisPool) {
     8             synchronized (JedisPoolUtil.class) {
     9                 if (null == jedisPool) {
    10                     // 创建连接池的配置文件,JedisPool的配置参数大部分是由这个配置文件决定的
    11                     JedisPoolConfig poolConfig = new JedisPoolConfig();
    12                     // 控制一个pool最多有多少个jedis实例
    13                     poolConfig.setMaxActive(1000);
    14                     // 控制一个pool最多有多少个状态为idle的jedis实例(最大空闲连接数)(要有这么多空闲的连接,不然不给创建)
    15                     poolConfig.setMaxIdle(32);
    16                     // 创建实例的最大等待时间(因为是上了锁的,所以可能会等待)
    17                     poolConfig.setMaxWait(100 * 1000);
    18                     // 在获取连接时 检查有效性,一般为false
    19                     poolConfig.setTestOnBorrow(true);
    20 
    21                     // 这个连接池 从 6379 这个端口获取连接
    22                     jedisPool = new JedisPool(poolConfig, "192.168.89.128",
    23                             6379);
    24                 }
    25             }
    26         }
    27         return jedisPool;
    28     }
    29 
    30     // 将 jedis 释放回 jedisPool
    31     public static void releaseJedis(JedisPool jedisPool, Jedis jedis) {
    32         if (jedis != null) {
    33             jedisPool.returnResourceObject(jedis);
    34         }
    35     }
    36 }
     1 JedisPool的配置参数大部分是由JedisPoolConfig的对应项来赋值的。
     2 
     3 
     4 maxActive:控制一个pool可分配多少个jedis实例,通过pool.getResource()来获取;如果赋值为-1,则表示不限制;如果pool已经分配了maxActive个jedis实例,则此时pool的状态为exhausted。
     5 maxIdle:控制一个pool最多有多少个状态为idle(空闲)的jedis实例;
     6 whenExhaustedAction:表示当pool中的jedis实例都被allocated完时,pool要采取的操作;默认有三种。
     7  WHEN_EXHAUSTED_FAIL --> 表示无jedis实例时,直接抛出NoSuchElementException;
     8  WHEN_EXHAUSTED_BLOCK --> 则表示阻塞住,或者达到maxWait时抛出JedisConnectionException;
     9  WHEN_EXHAUSTED_GROW --> 则表示新建一个jedis实例,也就说设置的maxActive无用;
    10 maxWait:表示当borrow一个jedis实例时,最大的等待时间,如果超过等待时间,则直接抛JedisConnectionException;
    11 testOnBorrow:获得一个jedis实例的时候是否检查连接可用性(ping());如果为true,则得到的jedis实例均是可用的;
    12 
    13 
    14 testOnReturn:return 一个jedis实例给pool时,是否检查连接可用性(ping());
    15 
    16 
    17 testWhileIdle:如果为true,表示有一个idle object evitor线程对idle object进行扫描,如果validate失败,此object会被从pool中drop掉;这一项只有在timeBetweenEvictionRunsMillis大于0时才有意义;
    18 
    19 
    20 timeBetweenEvictionRunsMillis:表示idle object evitor两次扫描之间要sleep的毫秒数;
    21 
    22 
    23 numTestsPerEvictionRun:表示idle object evitor每次扫描的最多的对象数;
    24 
    25 
    26 minEvictableIdleTimeMillis:表示一个对象至少停留在idle状态的最短时间,然后才能被idle object evitor扫描并驱逐;这一项只有在timeBetweenEvictionRunsMillis大于0时才有意义;
    27 
    28 
    29 softMinEvictableIdleTimeMillis:在minEvictableIdleTimeMillis基础上,加入了至少minIdle个对象已经在pool里面了。如果为-1,evicted不会根据idle time驱逐任何对象。如果minEvictableIdleTimeMillis>0,则此项设置无意义,且只有在timeBetweenEvictionRunsMillis大于0时才有意义;
    30 
    31 
    32 lifo:borrowObject返回对象时,是采用DEFAULT_LIFO(last in first out,即类似cache的最频繁使用队列),如果为False,则表示FIFO队列;
    33 
    34 
    35 ==================================================================================================================
    36 其中JedisPoolConfig对一些参数的默认设置如下:
    37 testWhileIdle=true
    38 minEvictableIdleTimeMills=60000
    39 timeBetweenEvictionRunsMillis=30000
    40 numTestsPerEvictionRun=-1

      

  • 相关阅读:
    觅踪2
    构建之法阅读笔记08
    觅踪1
    暑期第四周学习周总结
    暑期第三周学习周总结
    暑期第二周学习周总结
    数据库程序设计第九天--整合总结
    数据库程序设计第八天--隔离人员权限
    数据库程序设计第七天--隔离地权限
    数据库程序设计第六天--管理员权限
  • 原文地址:https://www.cnblogs.com/xuzekun/p/7448547.html
Copyright © 2020-2023  润新知