Redis学习之API学习及Jedis源码原理分析 Redis学习之Jedis源码原理分析探究(BIO手写Jedis客户端)

  Redis是一个开源的使用ANSI C语言编写、遵守BSD协议、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。 我们在进行Java项目开发的时候,如果要使用Redis数据库,那么常常是通过Redis的Java客户端来简化Redis的使用,例如Redisson,Jedis,lettuce等等,我们本篇就以Jedis为例进行Redis的学习以及Jedis源码的探究。

一、Redis常见API

  由于Redis有5中数据类型,每种数据类型的基本操作API也存在差异,同时Redis有数种部署模式,在使用时,也就存在直接访问以及集群访问两种情况,因此在调用API时也有所差别。

  1、直接访问模式

  我们如果是单机、主从乃至哨兵模式时,都是直接对接点进行访问,因此通过Jedis进行API访问时,代码如下所示:

public class JedisApi {
    private Jedis jedis;
    public String KEY = "monkey";
    public String VALUES = "2019";

    @Before
    public void setUp() {
        jedis = new Jedis("192.168.0.31", 6379);
    }

    /***
     * 通过我们jedis对redis的key进行相应的操作
     */
    @org.junit.Test
    public void testKey() {
        System.out.println("清空数据:" + jedis.flushDB());//清空当前数据库
        System.out.println("判断某个键是否存在:" + jedis.exists("username"));
        System.out.println("新增<'username','zzh'>的键值对:" + jedis.set("username", "zzh"));
        Set<String> keys = jedis.keys("*");
        System.out.println("系统中所有的键如下:" + keys);
        System.out.println("删除键password:" + jedis.del("username"));
        System.out.println("查看键username所存储的值的类型:" + jedis.type("username"));
    }

    /***
     * 剩余时间 秒
     */
    @Test
    public void testTtl() {
        long ttl = jedis.ttl(KEY);
        System.out.println("倒计时时间 :" + ttl);
    }

    /***
     * 剩余时间 毫秒
     * 区别 单位不一样
     */

    @Test
    public void testPttl() {
        long pttl = jedis.pttl(KEY);
        System.out.println("pttl is :" + pttl);
    }

    /***
     * Jedis操作redis的字符串
     */
    @Test
    public void testString() {
        jedis.flushDB();
        System.out.println(jedis.set("key3", "value3"));
        System.out.println("在key3后面加入值:" + jedis.append("key3", "End"));
        System.out.println("key3的值:" + jedis.get("key3"));
        System.out.println("增加多个键值对:" + jedis.mset("key01", "value01", "key02", "value02", "key03", "value03"));
        System.out.println("获取多个键值对:" + jedis.mget("key01", "key02", "key03"));
        System.out.println("获取多个键值对:" + jedis.mget("key01", "key02", "key03", "key04"));
        System.out.println("删除多个键值对:" + jedis.del(new String[]{"key01", "key02"}));
        System.out.println("获取多个键值对:" + jedis.mget("key01", "key02", "key03"));
        jedis.flushDB();
        System.out.println("===========新增键值对防止覆盖原先值==============");
        System.out.println(jedis.setnx("key1", "value1"));
        System.out.println(jedis.setnx("key2", "value2"));
        System.out.println(jedis.setnx("key2", "value2-new"));
        System.out.println(jedis.get("key1"));
        System.out.println(jedis.get("key2"));

        System.out.println("===========获取原值,更新为新值==========");//GETSET is an atomic set this value and return the old value command.
        System.out.println(jedis.getSet("key2", "key2GetSet"));
        System.out.println(jedis.get("key2"));
    }

    @Test
    public void testList() {
        jedis.flushDB();
        System.out.println("===========添加一个list===========");
        jedis.lpush("collections", "monkey", "zhangsan", "wangwu", "xiaoming", "xiaoer", "tangseng");
        System.out.println("collections的内容:" + jedis.lrange("collections", 0, -1));
        System.out.println("collections的长度:" + jedis.llen("collections"));
        jedis.lpush("sortedList排序后", "3", "6", "2", "0", "7", "4");
        System.out.println(jedis.sort("sortedList排序后"));
        System.out.println("sortedList排序后:" + jedis.lrange("sortedList排序后", 0, -1));
    }

    /***
     * 键值对方式
     */
    @Test
    public void testMset() {
        jedis.mset(new String[]{"name", "monkey", "age", "18", "qq", "111111"});
        System.out.printf("姓名:%s,年龄:%s,联系方式:%s", jedis.get("name"), jedis.get("age"), jedis.get("qq"));
    }

    /***
     * 不能重复 set
     */
    @Test
    public void testSet() {
        jedis.flushDB();
        System.out.println("============向集合中添加元素============");
        System.out.println(jedis.sadd("eleSet", "e1", "e2", "e4", "e3", "e0", "e8", "e7", "e5"));
        System.out.println(jedis.sadd("eleSet", "e6"));
        System.out.println(jedis.sadd("eleSet", "e6"));//重复问题 1 or 0
        System.out.println("eleSet的所有元素为:" + jedis.smembers("eleSet"));

        System.out.println("=================================");
        System.out.println(jedis.sadd("eleSet1", "e1", "e2", "e4", "e3", "e0", "e8", "e7", "e5"));
        System.out.println("============集合运算=================");
        System.out.println("eleSet和eleSet1的交集:" + jedis.sinter("eleSet", "eleSet1"));
        System.out.println("eleSet和eleSet1的并集:" + jedis.sunion("eleSet", "eleSet1"));
        System.out.println("eleSet和eleSet1的差集:" + jedis.sdiff("eleSet", "eleSet1"));//eleSet1中有,eleSet2中没有
    }

    /***
     * 散列
     */
    @Test
    public void testHash() {
        jedis.flushDB();
        Map<String, String> map = new HashMap<String, String>();
        map.put("zhangsan", "a");
        map.put("canglaoshi", "b");
        map.put("monkey", "c");
        map.put("wangwu", "d");
        jedis.hmset("hash", map);
        jedis.hset("hash", "luban", "e");
        System.out.println("散列hash的所有键值对为:" + jedis.hgetAll("hash"));//return Map<String,String>
        System.out.println("散列hash的所有键为:" + jedis.hkeys("hash"));//return Set<String>
        System.out.println("散列hash的所有值为:" + jedis.hvals("hash"));//return List<String>

    }
}

  执行结果如下:

清空数据:OK
判断某个键是否存在:false
新增<'username','zzh'>的键值对:OK
系统中所有的键如下:[username]
删除键password:1
查看键username所存储的值的类型:none
============向集合中添加元素============
8
1
0
eleSet的所有元素为:[e7, e2, e4, e0, e8, e5, e1, e3, e6]
=================================
8
============集合运算=================
eleSet和eleSet1的交集:[e3, e7, e2, e4, e0, e8, e5, e1]
eleSet和eleSet1的并集:[e6, e3, e7, e4, e0, e1, e5, e2, e8]
eleSet和eleSet1的差集:[e6]
倒计时时间 :-2
散列hash的所有键值对为:{zhangsan=a, wangwu=d, monkey=c, luban=e, canglaoshi=b}
散列hash的所有键为:[zhangsan, wangwu, monkey, luban, canglaoshi]
散列hash的所有值为:[c, b, d, a, e]
===========添加一个list===========
collections的内容:[tangseng, xiaoer, xiaoming, wangwu, zhangsan, monkey]
collections的长度:6
[0, 2, 3, 4, 6, 7]
sortedList排序后:[4, 7, 0, 2, 6, 3]
姓名:monkey,年龄:18,联系方式:111111pttl is :-2
OK
在key3后面加入值:9
key3的值:value3End
增加多个键值对:OK
获取多个键值对:[value01, value02, value03]
获取多个键值对:[value01, value02, value03, null]
删除多个键值对:2
获取多个键值对:[null, null, value03]
===========新增键值对防止覆盖原先值==============
1
1
0
value1
value2
===========获取原值,更新为新值==========
value2
key2GetSet

  2、集群访问模式

  如果是Redis集群,那么Jedis在客户端初始化时将使用JedisCluster,由于Redis集群下数据是分节点存储的,因此直接访问模式下的部分Redis API将不支持,测试代码如下:

public class JavaStyle {
    private static JedisCluster jedis;

    static {
        Set<HostAndPort> jedisClusterNodes = new HashSet<HostAndPort>();
        jedisClusterNodes.add(new HostAndPort("127.0.0.1", 7001));
        jedisClusterNodes.add(new HostAndPort("127.0.0.1", 7002));
        jedisClusterNodes.add(new HostAndPort("127.0.0.1", 7003));
        jedisClusterNodes.add(new HostAndPort("127.0.0.1", 7004));
        jedisClusterNodes.add(new HostAndPort("127.0.0.1", 7005));
        jedisClusterNodes.add(new HostAndPort("127.0.0.1", 7006));
        JedisPoolConfig cfg = new JedisPoolConfig();
        cfg.setMaxTotal(500);
        cfg.setMaxIdle(100);
        cfg.setMaxWaitMillis(2000);
        cfg.setTestOnBorrow(true);
        jedis = new JedisCluster(jedisClusterNodes, cfg);
    }

    /***
     * TODO API不支持批量
     */
    @Test
    public void test() {
        System.out.println("增加多个键值对:" + jedis.mset("key01", "value01", "key02", "value02"));
        //命令的时候才会去连接连接对吧
        System.out.println("获取多个键值对:" + jedis.mget("key01", "key02", "key03"));
        System.out.println("获取多个键值对:" + jedis.mget("key01", "key02", "key03", "key04"));
    }

    @Test
    public void testKey2() throws InterruptedException {
        System.out.println("新增<'username','monkey'>的键值对:" + jedis.set("username", "monkey"));
    }

    @Test
    public void testKey() throws InterruptedException {
        // System.out.println("清空数据:"+jedis.flushDB());  不支持
        System.out.println("判断某个键是否存在:" + jedis.exists("username"));
        System.out.println("新增<'username','monkey'>的键值对:" + jedis.set("username", "monkey"));
        System.out.println("是否存在:" + jedis.exists("name"));
        System.out.println("新增<'password','password'>的键值对:" + jedis.set("password", "password"));
        //Set<String> keys = jedis.keys("*");  不支持
        // System.out.println("系统中所有的键如下:"+keys);
        System.out.println("删除键password:" + jedis.del("password"));
        System.out.println("判断键password是否存在:" + jedis.exists("password"));
        System.out.println("设置键username的过期时间为5s:" + jedis.expire("username", 5));
        TimeUnit.SECONDS.sleep(2);
        System.out.println("查看键username的剩余生存时间:" + jedis.ttl("username"));
        System.out.println("移除键username的生存时间:" + jedis.persist("username"));
        System.out.println("查看键username的剩余生存时间:" + jedis.ttl("username"));
        System.out.println("查看键username所存储的值的类型:" + jedis.type("username"));
    }

    /***
     * 字符串操作
     * memcached和redis同样有append的操作,但是memcached有prepend的操作,redis中并没有。
     * @throws InterruptedException
     */
    @Test
    public void testString() throws InterruptedException {
        //jedis.flushDB();
        System.out.println("===========增加数据===========");
        System.out.println(jedis.set("key1", "value1"));
        System.out.println(jedis.set("key2", "value2"));
        System.out.println(jedis.set("key3", "value3"));
        System.out.println("删除键key2:" + jedis.del("key2"));
        System.out.println("获取键key2:" + jedis.get("key2"));
        System.out.println("修改key1:" + jedis.set("key1", "value1Changed"));
        System.out.println("获取key1的值:" + jedis.get("key1"));
        System.out.println("在key3后面加入值:" + jedis.append("key3", "End"));
        System.out.println("key3的值:" + jedis.get("key3"));//jedis.flushDB();
        System.out.println("===========新增键值对防止覆盖原先值==============");
        System.out.println(jedis.setnx("key1", "value1"));
        System.out.println(jedis.setnx("key2", "value2"));
        System.out.println(jedis.setnx("key2", "value2-new"));
        System.out.println(jedis.get("key1"));
        System.out.println(jedis.get("key2"));

        System.out.println("===========新增键值对并设置有效时间=============");
        System.out.println(jedis.setex("key3", 2, "value3"));
        System.out.println(jedis.get("key3"));
        TimeUnit.SECONDS.sleep(3);
        System.out.println(jedis.get("key3"));

        System.out.println("===========获取原值,更新为新值==========");//GETSET is an atomic set this value and return the old value command.
        System.out.println(jedis.getSet("key2", "key2GetSet"));
        System.out.println(jedis.get("key2"));

        System.out.println("获得key2的值的字串:" + jedis.getrange("key2", 2, 4));
    }

    /***
     * 整数和浮点数
     */
    @Test
    public void testNumber() {
        //jedis.flushDB();
        jedis.set("key1", "1");
        jedis.set("key2", "2");
        jedis.set("key3", "2.3");
        System.out.println("key1的值:" + jedis.get("key1"));
        System.out.println("key2的值:" + jedis.get("key2"));
        System.out.println("key1的值加1:" + jedis.incr("key1"));
        System.out.println("获取key1的值:" + jedis.get("key1"));
        System.out.println("key2的值减1:" + jedis.decr("key2"));
        System.out.println("获取key2的值:" + jedis.get("key2"));
        System.out.println("将key1的值加上整数5:" + jedis.incrBy("key1", 5));
        System.out.println("获取key1的值:" + jedis.get("key1"));
        System.out.println("将key2的值减去整数5:" + jedis.decrBy("key2", 5));
        System.out.println("获取key2的值:" + jedis.get("key2"));
    }

    /***
     * 列表
     */
    @Test
    public void testList() {
        //jedis.flushDB();
        System.out.println("===========添加一个list===========");
        jedis.lpush("collections", "ArrayList", "Vector", "Stack", "HashMap", "WeakHashMap", "LinkedHashMap");
        jedis.lpush("collections", "HashSet");
        jedis.lpush("collections", "TreeSet");
        jedis.lpush("collections", "TreeMap");
        System.out.println("collections的内容:" + jedis.lrange("collections", 0, -1));//-1代表倒数第一个元素,-2代表倒数第二个元素
        System.out.println("collections区间0-3的元素:" + jedis.lrange("collections", 0, 3));
        System.out.println("===============================");
        // 删除列表指定的值 ,第二个参数为删除的个数(有重复时),后add进去的值先被删,类似于出栈
        System.out.println("删除指定元素个数:" + jedis.lrem("collections", 2, "HashMap"));
        System.out.println("collections的内容:" + jedis.lrange("collections", 0, -1));
        System.out.println("删除下表0-3区间之外的元素:" + jedis.ltrim("collections", 0, 3));
        System.out.println("collections的内容:" + jedis.lrange("collections", 0, -1));
        System.out.println("collections列表出栈(左端):" + jedis.lpop("collections"));
        System.out.println("collections的内容:" + jedis.lrange("collections", 0, -1));
        System.out.println("collections添加元素,从列表右端,与lpush相对应:" + jedis.rpush("collections", "EnumMap"));
        System.out.println("collections的内容:" + jedis.lrange("collections", 0, -1));
        System.out.println("collections列表出栈(右端):" + jedis.rpop("collections"));
        System.out.println("collections的内容:" + jedis.lrange("collections", 0, -1));
        System.out.println("修改collections指定下标1的内容:" + jedis.lset("collections", 1, "LinkedArrayList"));
        System.out.println("collections的内容:" + jedis.lrange("collections", 0, -1));
        System.out.println("===============================");
        System.out.println("collections的长度:" + jedis.llen("collections"));
        System.out.println("获取collections下标为2的元素:" + jedis.lindex("collections", 2));
        System.out.println("===============================");
        jedis.lpush("sortedList", "3", "6", "2", "0", "7", "4");
        System.out.println("sortedList排序前:" + jedis.lrange("sortedList", 0, -1));
        System.out.println(jedis.sort("sortedList"));
        System.out.println("sortedList排序后:" + jedis.lrange("sortedList", 0, -1));
    }

    /***
     * set集合
     */
    @Test
    public void testSet() {
        //jedis.flushDB();
        System.out.println("============向集合中添加元素============");
        System.out.println(jedis.sadd("eleSet", "e1", "e2", "e4", "e3", "e0", "e8", "e7", "e5"));
        System.out.println(jedis.sadd("eleSet", "e6"));
        System.out.println(jedis.sadd("eleSet", "e6"));
        System.out.println("eleSet的所有元素为:" + jedis.smembers("eleSet"));
        System.out.println("删除一个元素e0:" + jedis.srem("eleSet", "e0"));
        System.out.println("eleSet的所有元素为:" + jedis.smembers("eleSet"));
        System.out.println("删除两个元素e7和e6:" + jedis.srem("eleSet", "e7", "e6"));
        System.out.println("eleSet的所有元素为:" + jedis.smembers("eleSet"));
        System.out.println("随机的移除集合中的一个元素:" + jedis.spop("eleSet"));
        System.out.println("随机的移除集合中的一个元素:" + jedis.spop("eleSet"));
        System.out.println("eleSet的所有元素为:" + jedis.smembers("eleSet"));
        System.out.println("eleSet中包含元素的个数:" + jedis.scard("eleSet"));
        System.out.println("e3是否在eleSet中:" + jedis.sismember("eleSet", "e3"));
        System.out.println("e1是否在eleSet中:" + jedis.sismember("eleSet", "e1"));
        System.out.println("e1是否在eleSet中:" + jedis.sismember("eleSet", "e5"));
        System.out.println("=================================");
        System.out.println(jedis.sadd("eleSet1", "e1", "e2", "e4", "e3", "e0", "e8", "e7", "e5"));
        System.out.println(jedis.sadd("eleSet2", "e1", "e2", "e4", "e3", "e0", "e8"));
        //  System.out.println("将eleSet1中删除e1并存入eleSet3中:"+jedis.smove("eleSet1", "eleSet3", "e1"));
        //  System.out.println("将eleSet1中删除e2并存入eleSet3中:"+jedis.smove("eleSet1", "eleSet3", "e2"));
        System.out.println("eleSet1中的元素:" + jedis.smembers("eleSet1"));
        System.out.println("eleSet3中的元素:" + jedis.smembers("eleSet3"));
        System.out.println("============集合运算=================");
        System.out.println("eleSet1中的元素:" + jedis.smembers("eleSet1"));
        System.out.println("eleSet2中的元素:" + jedis.smembers("eleSet2"));
        // System.out.println("eleSet1和eleSet2的交集:"+jedis.sinter("eleSet1","eleSet2"));
        //System.out.println("eleSet1和eleSet2的并集:"+jedis.sunion("eleSet1","eleSet2"));
        // System.out.println("eleSet1和eleSet2的差集:"+jedis.sdiff("eleSet1","eleSet2"));//eleSet1中有,eleSet2中没有
    }

    /***
     * 散列
     */
    @Test
    public void testHash() {
        //jedis.flushDB();
        Map<String, String> map = new HashMap<String, String>();
        map.put("key1", "value1");
        map.put("key2", "value2");
        map.put("key3", "value3");
        map.put("key4", "value4");
        jedis.hmset("hash", map);
        jedis.hset("hash", "key5", "value5");
        System.out.println("散列hash的所有键值对为:" + jedis.hgetAll("hash"));//return Map<String,String>
        System.out.println("散列hash的所有键为:" + jedis.hkeys("hash"));//return Set<String>
        System.out.println("散列hash的所有值为:" + jedis.hvals("hash"));//return List<String>
        System.out.println("将key6保存的值加上一个整数,如果key6不存在则添加key6:" + jedis.hincrBy("hash", "key6", 6));
        System.out.println("散列hash的所有键值对为:" + jedis.hgetAll("hash"));
        System.out.println("将key6保存的值加上一个整数,如果key6不存在则添加key6:" + jedis.hincrBy("hash", "key6", 3));
        System.out.println("散列hash的所有键值对为:" + jedis.hgetAll("hash"));
        System.out.println("删除一个或者多个键值对:" + jedis.hdel("hash", "key2"));
        System.out.println("散列hash的所有键值对为:" + jedis.hgetAll("hash"));
        System.out.println("散列hash中键值对的个数:" + jedis.hlen("hash"));
        System.out.println("判断hash中是否存在key2:" + jedis.hexists("hash", "key2"));
        System.out.println("判断hash中是否存在key3:" + jedis.hexists("hash", "key3"));
        System.out.println("获取hash中的值:" + jedis.hmget("hash", "key3"));
        System.out.println("获取hash中的值:" + jedis.hmget("hash", "key3", "key4"));
    }

    @Test
    public void testSortedSet() {
        //jedis.flushDB();
        Map<String, Double> map = new HashMap<String, Double>();
        map.put("key2", 1.2);
        map.put("key3", 4.0);
        map.put("key4", 5.0);
        map.put("key5", 0.2);
        System.out.println(jedis.zadd("zset", 3, "key1"));
        System.out.println(jedis.zadd("zset", map));
        System.out.println("zset中的所有元素:" + jedis.zrange("zset", 0, -1));
        System.out.println("zset中的所有元素:" + jedis.zrangeWithScores("zset", 0, -1));
        System.out.println("zset中的所有元素:" + jedis.zrangeByScore("zset", 0, 100));
        System.out.println("zset中的所有元素:" + jedis.zrangeByScoreWithScores("zset", 0, 100));
        System.out.println("zset中key2的分值:" + jedis.zscore("zset", "key2"));
        System.out.println("zset中key2的排名:" + jedis.zrank("zset", "key2"));
        System.out.println("删除zset中的元素key3:" + jedis.zrem("zset", "key3"));
        System.out.println("zset中的所有元素:" + jedis.zrange("zset", 0, -1));
        System.out.println("zset中元素的个数:" + jedis.zcard("zset"));
        System.out.println("zset中分值在1-4之间的元素的个数:" + jedis.zcount("zset", 1, 4));
        System.out.println("key2的分值加上5:" + jedis.zincrby("zset", 5, "key2"));
        System.out.println("key3的分值加上4:" + jedis.zincrby("zset", 4, "key3"));
        System.out.println("zset中的所有元素:" + jedis.zrange("zset", 0, -1));
    }

    @Test
    public void testSort() {
        //jedis.flushDB();
        jedis.lpush("collections", "ArrayList", "Vector", "Stack", "HashMap", "WeakHashMap", "LinkedHashMap");
        System.out.println("collections的内容:" + jedis.lrange("collections", 0, -1));
        SortingParams sortingParameters = new SortingParams();
        System.out.println(jedis.sort("collections", sortingParameters.alpha()));
        System.out.println("===============================");
        jedis.lpush("sortedList", "3", "6", "2", "0", "7", "4");
        System.out.println("sortedList排序前:" + jedis.lrange("sortedList", 0, -1));
        System.out.println("升序:" + jedis.sort("sortedList", sortingParameters.asc()));
        System.out.println("升序:" + jedis.sort("sortedList", sortingParameters.desc()));
        System.out.println("===============================");
        jedis.lpush("userlist", "33");
        jedis.lpush("userlist", "22");
        jedis.lpush("userlist", "55");
        jedis.lpush("userlist", "11");
        jedis.hset("user:66", "name", "66");
        jedis.hset("user:55", "name", "55");
        jedis.hset("user:33", "name", "33");
        jedis.hset("user:22", "name", "79");
        jedis.hset("user:11", "name", "24");
        jedis.hset("user:11", "add", "beijing");
        jedis.hset("user:22", "add", "shanghai");
        jedis.hset("user:33", "add", "guangzhou");
        jedis.hset("user:55", "add", "chongqing");
        jedis.hset("user:66", "add", "xi'an");
        sortingParameters = new SortingParams();
        sortingParameters.get("user:*->name");
        sortingParameters.get("user:*->add");
        System.out.println(jedis.sort("userlist", sortingParameters));
    }
}

  测试结果如下:

判断某个键是否存在:false
新增<'username','monkey'>的键值对:OK
是否存在:false
新增<'password','password'>的键值对:OK
删除键password:1
判断键password是否存在:false
设置键username的过期时间为5s:1
查看键username的剩余生存时间:3
移除键username的生存时间:1
查看键username的剩余生存时间:-1
查看键username所存储的值的类型:string
============向集合中添加元素============
8
1
0
eleSet的所有元素为:[e1, e7, e5, e3, e0, e2, e8, e4, e6]
删除一个元素e0:1
eleSet的所有元素为:[e5, e3, e2, e8, e4, e7, e1, e6]
删除两个元素e7和e6:2
eleSet的所有元素为:[e8, e4, e1, e3, e2, e5]
随机的移除集合中的一个元素:e3
随机的移除集合中的一个元素:e4
eleSet的所有元素为:[e1, e2, e8, e5]
eleSet中包含元素的个数:4
e3是否在eleSet中:false
e1是否在eleSet中:true
e1是否在eleSet中:true
=================================
8
6
eleSet1中的元素:[e4, e1, e7, e5, e3, e0, e2, e8]
eleSet3中的元素:[]
============集合运算=================
eleSet1中的元素:[e4, e1, e7, e5, e3, e0, e2, e8]
eleSet2中的元素:[e2, e1, e4, e3, e0, e8]
散列hash的所有键值对为:{key1=value1, key2=value2, key5=value5, key3=value3, key4=value4}
散列hash的所有键为:[key1, key2, key5, key3, key4]
散列hash的所有值为:[value3, value1, value4, value2, value5]
将key6保存的值加上一个整数,如果key6不存在则添加key6:6
散列hash的所有键值对为:{key1=value1, key2=value2, key5=value5, key6=6, key3=value3, key4=value4}
将key6保存的值加上一个整数,如果key6不存在则添加key6:9
散列hash的所有键值对为:{key1=value1, key2=value2, key5=value5, key6=9, key3=value3, key4=value4}
删除一个或者多个键值对:1
散列hash的所有键值对为:{key1=value1, key5=value5, key6=9, key3=value3, key4=value4}
散列hash中键值对的个数:5
判断hash中是否存在key2:false
判断hash中是否存在key3:true
获取hash中的值:[value3]
获取hash中的值:[value3, value4]
新增<'username','monkey'>的键值对:OK
===========添加一个list===========
collections的内容:[TreeMap, TreeSet, HashSet, LinkedHashMap, WeakHashMap, HashMap, Stack, Vector, ArrayList]
collections区间0-3的元素:[TreeMap, TreeSet, HashSet, LinkedHashMap]
===============================
删除指定元素个数:1
collections的内容:[TreeMap, TreeSet, HashSet, LinkedHashMap, WeakHashMap, Stack, Vector, ArrayList]
删除下表0-3区间之外的元素:OK
collections的内容:[TreeMap, TreeSet, HashSet, LinkedHashMap]
collections列表出栈(左端):TreeMap
collections的内容:[TreeSet, HashSet, LinkedHashMap]
collections添加元素,从列表右端,与lpush相对应:4
collections的内容:[TreeSet, HashSet, LinkedHashMap, EnumMap]
collections列表出栈(右端):EnumMap
collections的内容:[TreeSet, HashSet, LinkedHashMap]
修改collections指定下标1的内容:OK
collections的内容:[TreeSet, LinkedArrayList, LinkedHashMap]
===============================
collections的长度:3
获取collections下标为2的元素:LinkedHashMap
===============================
sortedList排序前:[4, 7, 0, 2, 6, 3]
[0, 2, 3, 4, 6, 7]
sortedList排序后:[4, 7, 0, 2, 6, 3]
collections的内容:[LinkedHashMap, WeakHashMap, HashMap, Stack, Vector, ArrayList, TreeSet, LinkedArrayList, LinkedHashMap]
[ArrayList, HashMap, LinkedArrayList, LinkedHashMap, LinkedHashMap, Stack, TreeSet, Vector, WeakHashMap]
===============================
sortedList排序前:[4, 7, 0, 2, 6, 3, 4, 7, 0, 2, 6, 3]
升序:[0, 0, 2, 2, 3, 3, 4, 4, 6, 6, 7, 7]
升序:[7, 7, 6, 6, 4, 4, 3, 3, 2, 2, 0, 0]
===============================

redis.clients.jedis.exceptions.JedisDataException: ERR GET option of SORT denied in Cluster mode.
... ...
redis.clients.jedis.exceptions.JedisClusterException: No way to dispatch this command to Redis Cluster because keys have different slots.
... ...
1
4
zset中的所有元素:[key5, key2, key1, key3, key4]
zset中的所有元素:[[[107, 101, 121, 53],0.2], [[107, 101, 121, 50],1.2], [[107, 101, 121, 49],3.0], [[107, 101, 121, 51],4.0], [[107, 101, 121, 52],5.0]]
zset中的所有元素:[key5, key2, key1, key3, key4]
zset中的所有元素:[[[107, 101, 121, 53],0.2], [[107, 101, 121, 50],1.2], [[107, 101, 121, 49],3.0], [[107, 101, 121, 51],4.0], [[107, 101, 121, 52],5.0]]
zset中key2的分值:1.2
zset中key2的排名:1
删除zset中的元素key3:1
zset中的所有元素:[key5, key2, key1, key4]
zset中元素的个数:4
zset中分值在1-4之间的元素的个数:2
key2的分值加上5:6.2
key3的分值加上4:4.0
zset中的所有元素:[key5, key1, key3, key4, key2]
key1的值:1
key2的值:2
key1的值加1:2
获取key1的值:2
key2的值减1:1
获取key2的值:1
将key1的值加上整数5:7
获取key1的值:7
将key2的值减去整数5:-4
获取key2的值:-4
===========增加数据===========
OK
OK
OK
删除键key2:1
获取键key2:null
修改key1:OK
获取key1的值:value1Changed
在key3后面加入值:9
key3的值:value3End
===========新增键值对防止覆盖原先值==============
0
1
0
value1Changed
value2
===========新增键值对并设置有效时间=============
OK
value3
null
===========获取原值,更新为新值==========
value2
key2GetSet
获得key2的值的字串:y2G

  对于集群访问模式们也可以使用Spring配置文件自动导入,代码如下:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"/application.xml"})
public class SpringStyle {

    @Autowired
    JedisCluster jedis;

    @Test
    public void testKey() throws InterruptedException
    {
        // System.out.println("清空数据:"+jedis.flushDB());
        System.out.println("判断某个键是否存在:"+jedis.exists("username"));
        System.out.println("新增<'username','wukong'>的键值对:"+jedis.set("username", "wukong"));
        System.out.println("是否存在:"+jedis.exists("name"));
        System.out.println("新增<'password','password'>的键值对:"+jedis.set("password", "password"));
        //Set<String> keys = jedis.keys("*");
        // System.out.println("系统中所有的键如下:"+keys);
        System.out.println("删除键password:"+jedis.del("password"));
        System.out.println("判断键password是否存在:"+jedis.exists("password"));
        System.out.println("设置键username的过期时间为5s:"+jedis.expire("username", 5));
        TimeUnit.SECONDS.sleep(2);
        System.out.println("查看键username的剩余生存时间:"+jedis.ttl("username"));
        System.out.println("移除键username的生存时间:"+jedis.persist("username"));
        System.out.println("查看键username的剩余生存时间:"+jedis.ttl("username"));
        System.out.println("查看键username所存储的值的类型:"+jedis.type("username"));
    }

    /***
     * 字符串操作
     * memcached和redis同样有append的操作,但是memcached有prepend的操作,redis中并没有。
     * @throws InterruptedException
     */
    @Test
    public void testString() throws InterruptedException
    {
        //jedis.flushDB();
        System.out.println("===========增加数据===========");
        System.out.println(jedis.set("key1","value1"));
        System.out.println(jedis.set("key2","value2"));
        System.out.println(jedis.set("key3", "value3"));
        System.out.println("删除键key2:"+jedis.del("key2"));
        System.out.println("获取键key2:"+jedis.get("key2"));
        System.out.println("修改key1:"+jedis.set("key1", "value1Changed"));
        System.out.println("获取key1的值:"+jedis.get("key1"));
        System.out.println("在key3后面加入值:"+jedis.append("key3", "End"));
        System.out.println("key3的值:"+jedis.get("key3"));//jedis.flushDB();
        System.out.println("===========新增键值对防止覆盖原先值==============");
        System.out.println(jedis.setnx("key1", "value1"));
        System.out.println(jedis.setnx("key2", "value2"));
        System.out.println(jedis.setnx("key2", "value2-new"));
        System.out.println(jedis.get("key1"));
        System.out.println(jedis.get("key2"));

        System.out.println("===========新增键值对并设置有效时间=============");
        System.out.println(jedis.setex("key3", 2, "value3"));
        System.out.println(jedis.get("key3"));
        TimeUnit.SECONDS.sleep(3);
        System.out.println(jedis.get("key3"));

        System.out.println("===========获取原值,更新为新值==========");//GETSET is an atomic set this value and return the old value command.
        System.out.println(jedis.getSet("key2", "key2GetSet"));
        System.out.println(jedis.get("key2"));

        System.out.println("获得key2的值的字串:"+jedis.getrange("key2", 2, 4));
    }
}

  配置文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <property name="maxTotal" value="500"></property>
        <property name="maxIdle" value="100"></property>
        <property name="maxWaitMillis" value="2000"></property>
        <property name="testOnBorrow" value="true"></property>
    </bean>

    <bean id="hostAndPort1" class="redis.clients.jedis.HostAndPort">
        <constructor-arg name="host" value="127.0.0.1"></constructor-arg>
        <constructor-arg name="port" value="7001"></constructor-arg>
    </bean>
    <bean id="hostAndPort2" class="redis.clients.jedis.HostAndPort">
        <constructor-arg name="host" value="127.0.0.1"></constructor-arg>
        <constructor-arg name="port" value="7002"></constructor-arg>
    </bean>
    <bean id="hostAndPort3" class="redis.clients.jedis.HostAndPort">
        <constructor-arg name="host" value="127.0.0.1"></constructor-arg>
        <constructor-arg name="port" value="7003"></constructor-arg>
    </bean>
    <bean id="hostAndPort4" class="redis.clients.jedis.HostAndPort">
        <constructor-arg name="host" value="127.0.0.1"></constructor-arg>
        <constructor-arg name="port" value="7004"></constructor-arg>
    </bean>
    <bean id="hostAndPort5" class="redis.clients.jedis.HostAndPort">
        <constructor-arg name="host" value="192.168.0.13"></constructor-arg>
        <constructor-arg name="port" value="7005"></constructor-arg>
    </bean>
    <bean id="hostAndPort6" class="redis.clients.jedis.HostAndPort">
        <constructor-arg name="host" value="192.168.0.13"></constructor-arg>
        <constructor-arg name="port" value="7006"></constructor-arg>
    </bean>

    <bean id="redisCluster" class="redis.clients.jedis.JedisCluster">
        <constructor-arg name="nodes">
            <set>
                <ref bean="hostAndPort1"></ref>
                <ref bean="hostAndPort2"></ref>
                <ref bean="hostAndPort3"></ref>
                <ref bean="hostAndPort4"></ref>
                <ref bean="hostAndPort5"></ref>
                <ref bean="hostAndPort6"></ref>
            </set>
        </constructor-arg>
        <constructor-arg name="poolConfig">
            <ref bean="jedisPoolConfig"></ref>
        </constructor-arg>
    </bean>
</beans>

  测试结果如下:

===========增加数据===========
OK
OK
OK
删除键key2:1
获取键key2:null
修改key1:OK
获取key1的值:value1Changed
在key3后面加入值:9
key3的值:value3End
===========新增键值对防止覆盖原先值==============
0
1
0
value1Changed
value2
===========新增键值对并设置有效时间=============
OK
value3
null
===========获取原值,更新为新值==========
value2
key2GetSet
获得key2的值的字串:y2G

  3、Redis数据库监控

  我们还可以通过Jedis客户端对数据库进行监控,代码如下:

public class RedisMonitor {

    static class MonitorTask implements Runnable {
        private Jedis jedis;

        public MonitorTask(Jedis jedis) {
            this.jedis = jedis;
        }

        @Override
        public void run() {
            jedis.monitor(new JedisMonitor() {
                @Override
                public void onCommand(String command) {
                    System.out.println(command);
                }
            });
        }
    }

    public static void main(String[] args) {
        MonitorTask monitorTask = new MonitorTask(new Jedis("127.0.0.1", 6379));
        new Thread(monitorTask).start();

    }
}

  当我们后台用命令进行Redis数据库访问时,会打印具体日志,如:

1586284459.902139 [0 127.0.0.1:61929] "COMMAND"
1586284479.140059 [0 127.0.0.1:61929] "set" "key1" "value1"
1586284486.786536 [0 127.0.0.1:61929] "get" "key1"

  可以用作本地开发测试或者用于数据库监控。

二、Jedis源码原理分析

  在Redis的使用过程中,大多数人都是使用现成的客户端,如Jedis,Redisson,Lettuce。因此本文研究用BIO的方式手写Redis客户端尝试,对Jedis进行源码及原理探究。由于篇幅问题,此处内容请转到:Redis学习之Jedis源码原理分析探究(BIO手写Jedis客户端)

猜你喜欢

转载自www.cnblogs.com/jing99/p/12657552.html