zoukankan      html  css  js  c++  java
  • Jedis

    概述

    Jedis:一款java操作redis数据库的工具。是Redis官方推荐的Java连接开发工具。要在Java开发中使用好Redis中间件,必须对Jedis熟悉才能写成漂亮的代码。

    使用java连接Redis时,要在Redis的配置文件中设置bind 0.0.0.0

    Jedis所需的jar包依赖

    <dependency>
        <groupId>redis.clients</groupId>
        <artifactId>jedis</artifactId>
        <version>3.1.0</version>
    </dependency>
    

    基本使用

    //1. 获取连接
    Jedis jedis = new Jedis("localhost",6379);
    //2. 操作
    jedis.set("username","zhangsan");
    //3. 关闭连接
    jedis.close();
    

    测试连通性

    Jedis的基本使用非常简单,只需要创建Jedis对象的时候指定host,port, password即可。当然,Jedis对象有很多构造方法,都大同小异,只是对应和Redis连接的socket的参数不一样而已。

    public class TestRedisPing {
        public static void main(String[] args) {
            //创建连接
            Jedis jedis=new Jedis("192.168.81.130", 6379);
            //设置密码 如果没有密码可以不设置
            jedis.auth("123456");
            //调用 ping方法
            String ping = jedis.ping();
            //输出PONG
            System.out.println(ping);
            jedis.close();
        }
    }
    

    Jedis操作Redis中的数据结构

    key

    public static void main(String[] args) {
        //创建连接
        Jedis jedis=new Jedis("192.168.81.130", 6379);
        //keys *
        Set<String> keys = jedis.keys("*");
        for (String key : keys) {
            System.out.println(key);
        }
        //判断是否存在k2
        System.out.println("是否存在k2" + jedis.exists("k2"));
        jedis.close();
    }
    

    string

    package com.coydone.redistest;
    
    import org.junit.After;
    import org.junit.Before;
    import org.junit.Test;
    import redis.clients.jedis.Jedis;
    
    import java.util.List;
    import java.util.Map;
    import java.util.Set;
    
    public class RedisTest {
        private Jedis jedis;
        @Before
        public void beforeRedis(){
            //1. 获取连接
            jedis=new Jedis("192.168.81.130", 6379);
        }
        @After
        public void afterRedis(){
            //3. 关闭连接
            jedis.close();
        }
        //keys * 查询所有的key
        @Test
        public void testKeys(){
            Set<String> keys = jedis.keys("*");
            for (String key : keys) {
                System.out.println(key);
            }
        }
    
        //string操作
        @Test
        public void testString(){
            //2. 操作
            //存储
            jedis.set("username","zhangsan");
            //获取
            String username = jedis.get("username");
            System.out.println(username);
    
            //可以使用setex()方法存储可以指定过期时间的 key value
            //将activecode:hehe键值对存入redis,并且20秒后自动删除该键值对
            jedis.setex("activecode",20,"hehe");
    
            jedis.mset("str1", "v1", "str2", "v2", "str3", "v3");
            System.out.println(jedis.mget("str1", "str2", "str3"));
        }
    }
    

    hash

    @Test
    public void testHash(){
        // 存储hash
        jedis.hset("user","name","lisi");
        jedis.hset("user","age","23");
        jedis.hset("user","gender","female");
    
        // 获取hash
        String name = jedis.hget("user", "name");
        System.out.println(name);
    
        // 获取hash的所有map中的数据
        Map<String, String> user = jedis.hgetAll("user");
        for (String value : user.values()) {
            System.out.println(value);
        }
    }
    

    list

    @Test
    public void testList(){
        //存储
        jedis.lpush("mylist","a","b","c");//从左边存
        jedis.rpush("mylist","a","b","c");//从右边存
        //范围获取
        List<String> list = jedis.lrange("mylist", 0, -1);
        for (String element : list) {
            System.out.println(element);
        }
        //弹出
        String element1 = jedis.lpop("mylist");//c
        System.out.println(element1);
    }
    

    set

    @Test
    public void testSet(){
        // set 存储
        jedis.sadd("myset","java","php","c++");
    
        //移除
        jedis.srem("myset", "php");
        System.out.println(jedis.smembers("myset").size());
    
        // set 获取
        Set<String> myset = jedis.smembers("myset");
        System.out.println(myset);
    }
    

    zset

    //zset 即为 sortedset
    @Test
    public void testZset(){
        // sortedset 存储
        jedis.zadd("mysortedset",3,"亚索");
        jedis.zadd("mysortedset",30,"劫");
        jedis.zadd("mysortedset",55,"永恩");
    
        // sortedset 获取
        Set<String> mysortedset = jedis.zrange("mysortedset", 0, -1);
    
        System.out.println(mysortedset);
    }
    

    事务提交

    基本操作

    public class TestReidsTranaction {
        public static void main(String[] args) {
            // 创建连接
            Jedis jedis = new Jedis("192.168.81.130", 6379);
             //监控key,如果改动了事务就被放弃
             /*
             jedis.watch("serialNum");
             jedis.set("serialNum","s#####################");
             jedis.unwatch();*/
             Transaction transaction = jedis.multi();//被当作一个命令进行执行
             Response<String> response = transaction.get("serialNum");
             transaction.set("serialNum","s002");
             response = transaction.get("serialNum");
             transaction.lpush("list3","a");
             transaction.lpush("list3","b");
             transaction.lpush("list3","c");
             transaction.exec();
             //2 transaction.discard();
             System.out.println("serialNum***"+response.get());
            jedis.close();
        }
    }
    

    事务加锁

    public class TestReidsTranactionLock {
        public boolean transMethod() {
            Jedis jedis = new Jedis("192.168.81.130", 6379);
            int balance;// 可用余额
            int debt;// 欠额
            int amtToSubtract = 10;// 实刷额度
            jedis.watch("balance");
            // jedis.set("balance","5");//此句不该出现,讲课方便。模拟其他程序已经修改了该条目
            balance = Integer.parseInt(jedis.get("balance"));
            if (balance < amtToSubtract) {
                jedis.unwatch();
                System.out.println("modify");
                jedis.close();
                return false;
            } else {
                System.out.println("***********transaction");
                Transaction transaction = jedis.multi();
                transaction.decrBy("balance", amtToSubtract);
                transaction.incrBy("debt", amtToSubtract);
                transaction.exec();
                balance = Integer.parseInt(jedis.get("balance"));
                debt = Integer.parseInt(jedis.get("debt"));
                System.out.println("*******" + balance);
                System.out.println("*******" + debt);
                jedis.close();
                return true;
            }
        }
        /**
         * 通俗点讲,watch命令就是标记一个键,如果标记了一个键, 在提交事务前如果该键被别人修改过,那事务就会失败,这种情况通常可以在程序中 重新再尝试一次。
         * 首先标记了键balance,然后检查余额是否足够,不足就取消标记,并不做扣减; 足够的话,就启动事务进行更新操作,
         * 如果在此期间键balance被其它人修改, 那在提交事务(执行exec)时就会报错, 程序中通常可以捕获这类错误再重新执行一次,直到成功。
         */
        public static void main(String[] args) {
            TestReidsTranactionLock test = new TestReidsTranactionLock();
            boolean retValue = test.transMethod();
            System.out.println("main retValue-------: " + retValue);
        }
    }
    

    主从复制

    public class TestReidsMS {
        public static void main(String[] args) throws InterruptedException {
            // 创建连接
            Jedis jedis_M = new Jedis("192.168.120.129", 6379);
            Jedis jedis_S = new Jedis("192.168.120.129", 6380);
            jedis_S.slaveof("127.0.0.1", 6379);
            jedis_M.set("k6", "v6");
            Thread.sleep(500);
            System.out.println(jedis_S.get("k6"));
            jedis_M.close();
            jedis_S.close();
        }
    }
    

    集群连接

    public class ClusterConnection{
        public static final String HOST = "192.168.81.130";
        public static final Integer HOST_IP = "7001";
        public static void main(String[] args){
            Set<HostAndPort> nodes = new HashSet<>();
            nodes.add(new HostAndPort(HOST,7001));
            nodes.add(new HostAndPort(HOST,7002));
            nodes.add(new HostAndPort(HOST,7003));
            nodes.add(new HostAndPort(HOST,7004));
            nodes.add(new HostAndPort(HOST,7005));
            nodes.add(new HostAndPort(HOST,7006));
            
            JedisCluster jedisCluster = new JedisCluster(nodes);
            jedisCluster.set("name","zhangsan");
            System.out.println(jedisCluster.get("name"));
            
            //关闭连接
            jedisCluster.close();
    	}
    }
    

    jedis连接池

    jedis连接池是基于apache-commons pool2实现的。在构建连接池对象的时候,需要提供池对象的配置对象,及JedisPoolConfig(继承自GenericObjectPoolConfig)。我们可以通过这个配置对象对连接池进行相关参数的配置(如最大连接数,最大空数等)。

    JedisPool使用

    package com.coydone.redistest;
    
    import redis.clients.jedis.Jedis;
    import redis.clients.jedis.JedisPool;
    import redis.clients.jedis.JedisPoolConfig;
    
    //1. 创建JedisPool连接池对象
    //2. 调用方法 getResource()方法获取Jedis连接
    public class RedisPoolTest {
        public static void main(String[] args) {
            //0.创建一个配置对象
            JedisPoolConfig config = new JedisPoolConfig();
            config.setMaxTotal(50);
            config.setMaxIdle(10);
    
            //1.创建Jedis连接池对象
            JedisPool jedisPool = new JedisPool(config,"192.168.81.130",6379);
    
            //2.获取连接
            Jedis jedis = jedisPool.getResource();
            //3. 使用
            jedis.set("name","zhangsan");
            System.out.println(jedis.get("name"));
    
            //4. 关闭 归还到连接池中
            jedis.close();
        }
    }
    

    使用redis存储对象

    public class JedisPoolApp {
        public static void main(String[] args) {
            JedisPoolConfig config = new JedisPoolConfig();
            //配置连接池的相关信息
            poolConfig.setMaxTotal(100);
            poolConfig.setMaxIdle(80);
            poolConfig.setMinIdle(20);
            poolConfig.setMaxWaitMillis(2000);
            JedisPool jedisPool=new JedisPool(config,"192.168.81.130",6379);
            //从连接池里面得到连接
            Jedis jedis = jedisPool.getResource();
            //User类:name address
            User user =new User("小明","武汉");
    		//使用fastjson:对象转json字符串
            jedis.set("user:1", JSON.toJSONString(user));
            String json = jedis.get("user:1");
            System.out.println(json);
            //json转对象
            User user1=JSON.parseObject(json,User.class);
            System.out.println(user1.getName()+"  "+user1.getAddress());
            jedis.close();//还到池里面
        }
    }
    

    连接池工具类

    //需要加载配置文件jedis.properties
    public class JedisPoolUtils {
        private static JedisPool jedisPool;
        static{
            //读取配置文件
            InputStream is = JedisPoolUtils.class.getClassLoader().getResourceAsStream("jedis.properties");
            //创建Properties对象
            Properties pro = new Properties();
            //关联文件
            try {
                pro.load(is);
            } catch (IOException e) {
                e.printStackTrace();
            }
            //获取数据,设置到JedisPoolConfig中
            JedisPoolConfig config = new JedisPoolConfig();
            config.setMaxTotal(Integer.parseInt(pro.getProperty("maxTotal")));
            config.setMaxIdle(Integer.parseInt(pro.getProperty("maxIdle")));
    
            //初始化JedisPool
            jedisPool = new JedisPool(config,pro.getProperty("host"),Integer.parseInt(pro.getProperty("port")));
        }
        /**
    	* 获取连接方法
    	*/
        public static Jedis getJedis(){
            return jedisPool.getResource();
        }
    }
    
    //直接在代码里进行配置
    public class JedisPoolUtil {
        private static volatile JedisPool jedisPool = null;// 被volatile修饰的变量不会被本地线程缓存,对该变量的读写都是直接操作共享内存。
        private JedisPoolUtil() {
        }
        public static JedisPool getJedisPoolInstance() {
            if (null == jedisPool) {
                synchronized (JedisPoolUtil.class) {
                    if (null == jedisPool) {
                        JedisPoolConfig poolConfig = new JedisPoolConfig();
                        poolConfig.setMaxTotal(1000);
                        poolConfig.setMaxIdle(32);
                        poolConfig.setMaxWaitMillis(100 * 1000);
                        poolConfig.setTestOnBorrow(true);
                        jedisPool = new JedisPool(poolConfig, "192.168.120.129", 6379);
                    }
                }
            }
            return jedisPool;
        }
        public static void release(JedisPool jedisPool, Jedis jedis) {
            if (null != jedis) {
                Jedis jedis2 = null;
                try {
                    jedis2 = jedisPool.getResource();
                } finally {
                    jedis2.close();
                }
            }
        }
    }
    
    //使用
    public class TestJedisPool {
        public static void main(String[] args) {
            JedisPool jedisPool = JedisPoolUtil.getJedisPoolInstance();
            Jedis jedis = null;
            try {
                jedis = jedisPool.getResource();
                jedis.set("k18", "v183");
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                JedisPoolUtil.release(jedisPool, jedis);
            }
        }
    }
    

    JedisPool配置

    JedisPool的配置参数大部分是由JedisPoolConfig的对应项来赋值的。
    
    maxTotal/maxActive:控制一个pool可分配多少个jedis实例,通过pool.getResource()来获取;如果赋值为-1,则表示不限制;如果pool已经分配了maxActive个jedis实例,则此时pool的状态为exhausted。
    maxIdle:控制一个pool最多有多少个状态为idle(空闲)的jedis实例;
    whenExhaustedAction:表示当pool中的jedis实例都被allocated完时,pool要采取的操作;默认有三种。
    WHEN_EXHAUSTED_FAIL --> 表示无jedis实例时,直接抛出NoSuchElementException;
    WHEN_EXHAUSTED_BLOCK --> 则表示阻塞住,或者达到maxWait时抛出JedisConnectionException;
    WHEN_EXHAUSTED_GROW --> 则表示新建一个jedis实例,也就说设置的maxActive无用;
    setMaxWaitMillis/maxWait:表示当borrow一个jedis实例时,最大的等待时间,如果超过等待时间,则直接抛JedisConnectionException;
    testOnBorrow:获得一个jedis实例的时候是否检查连接可用性(ping());如果为true,则得到的jedis实例均是可用的;
    
    testOnReturn:return 一个jedis实例给pool时,是否检查连接可用性(ping());
    
    testWhileIdle:如果为true,表示有一个idle object evitor线程对idle object进行扫描,如果validate失败,此object会被从pool中drop掉;这一项只有在timeBetweenEvictionRunsMillis大于0时才有意义;
    
    timeBetweenEvictionRunsMillis:表示idle object evitor两次扫描之间要sleep的毫秒数;
    
    numTestsPerEvictionRun:表示idle object evitor每次扫描的最多的对象数;
    
    minEvictableIdleTimeMillis:表示一个对象至少停留在idle状态的最短时间,然后才能被idle object evitor扫描并驱逐;这一项只有在timeBetweenEvictionRunsMillis大于0时才有意义;
    
    softMinEvictableIdleTimeMillis:在minEvictableIdleTimeMillis基础上,加入了至少minIdle个对象已经在pool里面了。如果为-1,evicted不会根据idle time驱逐任何对象。如果minEvictableIdleTimeMillis>0,则此项设置无意义,且只有在timeBetweenEvictionRunsMillis大于0时才有意义;
    
    lifo:borrowObject返回对象时,是采用DEFAULT_LIFO(last in first out,即类似cache的最频繁使用队列),如果为False,则表示FIFO队列;
    ====================================================================
    其中JedisPoolConfig对一些参数的默认设置如下:
    testWhileIdle=true
    minEvictableIdleTimeMills=60000
    timeBetweenEvictionRunsMillis=30000
    numTestsPerEvictionRun=-1
    
    coydone的博客
  • 相关阅读:
    洛谷 P3391 文艺平衡树
    [ZJOI2008]杀蚂蚁 Solution
    POJ P3667 Hotel——solution
    洛谷 P2469 [SDOI2010]星际竞速 解题报告
    POJ P2318 TOYS与POJ P1269 Intersecting Lines——计算几何入门题两道
    【linux】基础知识学习
    【linux】打包压缩命令
    【python】类file文件处理
    【python】使用asyncore进行异步通信
    【python】命令行解析工具getopt用法
  • 原文地址:https://www.cnblogs.com/coydone/p/13920928.html
Copyright © 2011-2022 走看看