Redis进阶(二)

1. redis事务

1.1. 命令
命令作用
Exec执行所有事务块内的命令
Watch监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断
Discard取消事务,放弃执行事务块内的所有命令。
Redis Unwatch取消 WATCH 命令对所有 key 的监视。
Redis Multi标记一个事务块的开始。
1.2. 概述

redis事务本质:一组命令的集合!一个命令中的所有命令都会被序列化,在事务执行过程中会按照顺序执行!一次性、顺序性、排他性!所有的命令都在事务队列中,并没有被直接执行!只有发起执行事务命令时才会按照顺序进行统一执行exec

---- 队列 命令1 命令2 命令3 队列 ------

redis事务能不能保证原子性:redis事务没有隔离级别的概念;redis单条命令是能够保证原子性的,但是redis事务并不能保证数据的原子性!

redis 事务流程:

  • 开启事务(multi)
  • 命令入队(命令1,命令2 。。。)
  • 执行事务(exec)
1.3. 正常执行事务
本机redis_01:0>multi
"OK"
本机redis_01:0>set k1 v1
"QUEUED"
本机redis_01:0>set k2 v2
"QUEUED"
本机redis_01:0>setnx k3 v3
"QUEUED"
本机redis_01:0>exec
 1)  "OK"
 2)  "OK"
 3)  "1"
本机redis_01:0>get k1
"v1"
本机redis_01:0>mget k1 k2 k3
 1)  "v1"
 2)  "v2"
 3)  "v3"
1.4. 取消/回滚事务
本机redis_01:0>multi
"OK"
本机redis_01:0>set a a 
"QUEUED"
本机redis_01:0>set b b
"QUEUED"
本机redis_01:0>discard 
"OK"
本机redis_01:0>mget a b
 1)  null
 2)  null
1.5. 编译时异常

代码有问题,redis命令有错;这种情况下事务中的所有命令都不会被执行

本机redis_01:0>multi
"OK"
本机redis_01:0>set n1 m1
"QUEUED"
本机redis_01:0>set n2 m2
"QUEUED"
本机redis_01:0>set n3
"ERR wrong number of arguments for 'set' command"
本机redis_01:0>exec
"EXECABORT Transaction discarded because of previous errors."
本机redis_01:0>mget n1 n2
 1)  null
 2)  null
1.6. 运行时异常

代码没问题,redis命令执行时报错;这种情况下,执行报错的那条redis命令失败,事务中其它正常的命令执行成功。

本机redis_01:0>set gold zhangsan
"OK"
本机redis_01:0>multi 
"OK"
本机redis_01:0>set key1 value1
"QUEUED"
本机redis_01:0>set key2 value2
"QUEUED"
本机redis_01:0>incrby gold 20
"QUEUED"
本机redis_01:0>exec
 1)  "OK"
 2)  "OK"
 3)  "ERR value is not an integer or out of range"
本机redis_01:0>mget key1 key2 gold
 1)  "value1"
 2)  "value2"
 3)  "zhangsan"
1.7. 悲观锁和乐观锁

悲观锁:不信任一切操作, 悲观并发控制实际上是“先取锁再访问”的保守策略,为数据处理的安全提供了保证 ,这样性能很低。

乐观锁(推荐):信任所有操作,只有更改数据的时候去判断下是否有人修改过这个数据; 如果冲突,则返回给用户异常信息,让用户决定如何去做。乐观锁适用于读多写少的场景,这样可以提高程序的吞吐量

  • 单线程实现悲观锁:
本机redis_01:0>set money 1000
"OK"
本机redis_01:0>watch money
"OK"
本机redis_01:0>multi
"OK"
本机redis_01:0>incrby money 20
"QUEUED"
本机redis_01:0>get money
"QUEUED"
本机redis_01:0>exec
 1)  "1020"
 2)  "1020"
  • 多线程实现悲观锁(客户端1):
本机redis_01:0>watch money
"OK"
本机redis_01:0>multi
"OK"
本机redis_01:0>incrby money 100
"QUEUED"
本机redis_01:0>get money
"QUEUED"
本机redis_01:0>
  • 当客户端1事务代码还没执行的时候客户端2 进行如下数据操作:
本机redis_01:0>incrby money 100
"1120"
  • 客户端1执行事务代码:事务执行失败,因为watch命令监听到数据已经发生了改变,故不执行此次事务命令
本机redis_01:0>watch money
"OK"
本机redis_01:0>multi
"OK"
本机redis_01:0>incrby money 100
"QUEUED"
本机redis_01:0>get money
"QUEUED"
本机redis_01:0>exec

本机redis_01:0>get money
"1120"

  • 更改为乐观锁实现:
本机redis_01:0>multi
"OK"
本机redis_01:0>incrby money 100
"QUEUED"
本机redis_01:0>get money
"QUEUED"
本机redis_01:0>exec
本机redis_01:0>unwatch # 如果事务执行失败使用unwatch释放锁从而实现乐观锁
"OK"
本机redis_01:0>get money
"1220"
本机redis_01:0>incrby money 100
"1320"

2. jedis客户端

2.1. springboot集成jedis
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>2.9.0</version>
</dependency>

2.2. 操作key相关命令
package com.acx.test;

import redis.clients.jedis.Jedis;

/**
 * key 命令
 */
public class RedisKeyTest {

    public static void main(String[] args) {
        Jedis jedis = new Jedis("127.0.0.1", 6379); //默认就是操作0号数据库
        jedis.auth("123456");

        System.out.println("set 命令!结果 = " + jedis.set("name", "zhangsan"));
        System.out.println("set 命令!结果 = " + jedis.set("name1", "lisi"));
        System.out.println("set 命令!结果 = " + jedis.set("age", "20"));
        System.out.println("set 命令!结果 = " + jedis.set("age1", "33"));
        System.out.println("set 命令!结果 = " + jedis.set("city", "beijing"));
        System.out.println("set 命令!结果 = " + jedis.set("city1", "上海"));

        /******************************************************************/
        System.out.println("执行keys命令!结果 = " + jedis.keys("*"));
        System.out.println("执行keys命令!结果 = " + jedis.keys("n*"));
        System.out.println("执行keys命令!结果 = " + jedis.keys("a*"));

        System.out.println("执行rename命令!结果 = " + jedis.rename("name", "xingming"));
        System.out.println("执行exists命令!结果 = " + jedis.exists("name", "xingming", "age"));
        System.out.println("执行move命令!结果 = " + jedis.move("age", 1));
        System.out.println("执行select命令选择数据库!结果 = " + jedis.select(1));
        jedis.select(0); // 切换会0号数据库
        jedis.set("area", "chain");
        System.out.println("执行expire设置key过期时间命令!结果 = " + jedis.expire("area", 100));
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("执行ttl命令查询剩余过期时间!结果 = " + jedis.ttl("area"));
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("执行pttl命令查询剩余过期时间(毫秒为单位)!结果 = " + jedis.pttl("area"));
        System.out.println("执行del删除key数据命令!结果 = " + jedis.del("city1"));
        System.out.println("验证删除是否成功!结果 = " + jedis.get("city1"));
        System.out.println("执行renamenx命令!当新key不存在时将 key 改名为 newkey !结果 = "
                + jedis.renamenx("age1", "age2"));
        System.out.println("执行flushdb命令!清空当前数据库的所有数据!结果 = " + jedis.flushDB());
        System.out.println("执行flushall命令!清空所有数据库(16个库)的数据!结果 = " + jedis.flushAll());
    }

}

  • 执行结果:
set 命令!结果 = OK
set 命令!结果 = OK
set 命令!结果 = OK
set 命令!结果 = OK
set 命令!结果 = OK
set 命令!结果 = OK
执行keys命令!结果 = [name, city1, city, name1, age, age1]
执行keys命令!结果 = [name, name1]
执行keys命令!结果 = [age, age1]
执行rename命令!结果 = OK
执行exists命令!结果 = 2
执行move命令!结果 = 1
执行select命令选择数据库!结果 = OK
执行expire设置key过期时间命令!结果 = 1
执行ttl命令查询剩余过期时间!结果 = 98
执行pttl命令查询剩余过期时间(毫秒为单位)!结果 = 95989
执行del删除key数据命令!结果 = 1
验证删除是否成功!结果 = null
执行renamenx命令!当新key不存在时将 key 改名为 newkey !结果 = 1
执行flushdb命令!清空当前数据库的所有数据!结果 = OK
执行flushall命令!清空所有数据库(16个库)的数据!结果 = OK

2.3. 操作string
package com.acx.test;

import redis.clients.jedis.Jedis;

/**
 * string 命令
 */
public class RedisStringTest {

    public static void main(String[] args) throws InterruptedException {
        Jedis jedis = new Jedis("127.0.0.1", 6379); //默认就是操作0号数据库
        jedis.auth("123456");

        System.out.println("执行set方法!结果 = " + jedis.set("name", "zhangsan"));
        System.out.println("执行mset批量插入!结果 = " + jedis.mset("age", "30", "gold", "100"));
        System.out.println("执行get方法! 结果 = " + jedis.get("name"));
        System.out.println("执行mget方法!批量查询!结果 = " + jedis.mget("name", "age", "gold"));
        System.out.println("执行append添加字符串方法!结果 = " + jedis.append("name", "666"));
        System.out.println("append之后的name = " + jedis.get("name"));
        System.out.println("执行setnx方法!如果key不存在就设置!结果 = " + jedis.setnx("name", "lisi"));
        System.out.println("执行incr数字加一方法!结果 = " + jedis.incr("gold"));
        System.out.println("gold = " + jedis.get("gold"));
        System.out.println("执行incrby自定义数字加法!结果 = " + jedis.incrBy("gold", 10));
        System.out.println("gold = " + jedis.get("gold"));
        System.out.println("执行decr减一方法!结果 = " + jedis.decr("gold"));
        System.out.println("gold = " + jedis.get("gold"));
        System.out.println("执行decrby减去一定量的方法!结果 = " + jedis.decrBy("gold", 5));
        System.out.println("gold = " + jedis.get("gold"));
        System.out.println("执行setex设置key并设置过期时间!结果 = " + jedis.setex("country", 100, "chain"));
        Thread.sleep(2000);
        System.out.println("country 剩余过期时间!结果 = " + jedis.ttl("country"));
        Thread.sleep(2000);
        System.out.println("country 剩余过期时间!结果 = " + jedis.ttl("country"));
        System.out.println("执行getrange命令!根据下标区间获取字符串!结果 = " + jedis.getrange("name", 0, -1));
        System.out.println("执行getrange命令!根据下标区间获取字符串!结果 = " + jedis.getrange("name", 1, 3));
        System.out.println("执行getset命令!先获取指定key的值再重新设置value!结果 = " + jedis.getSet("name", "lisi"));
        System.out.println("执行getset命令之后的结果 = " + jedis.get("name"));
    }

}

  • 运行结果:
执行set方法!结果 = OK
执行mset批量插入!结果 = OK
执行get方法! 结果 = zhangsan
执行mget方法!批量查询!结果 = [zhangsan, 30, 100]
执行append添加字符串方法!结果 = 11
append之后的name = zhangsan666
执行setnx方法!如果key不存在就设置!结果 = 0
执行incr数字加一方法!结果 = 101
gold = 101
执行incrby自定义数字加法!结果 = 111
gold = 111
执行decr减一方法!结果 = 110
gold = 110
执行decrby减去一定量的方法!结果 = 105
gold = 105
执行setex设置key并设置过期时间!结果 = OK
country 剩余过期时间!结果 = 98
country 剩余过期时间!结果 = 96
执行getrange命令!根据下标区间获取字符串!结果 = zhangsan666
执行getrange命令!根据下标区间获取字符串!结果 = han
执行getset命令!先获取指定key的值再重新设置value!结果 = zhangsan666
执行getset命令之后的结果 = lisi

2.4. 操作list
package com.acx.test;

import redis.clients.jedis.BinaryClient;
import redis.clients.jedis.Jedis;

/**
 * list 命令
 */
public class RedisListTest {

    public static void main(String[] args) {

        Jedis jedis = new Jedis("127.0.0.1", 6379); //默认就是操作0号数据库
        jedis.auth("123456");

        System.out.println("执行lpush命令!将一个或多个值插入到列表头部,从左往右插入!结果 = " + jedis.lpush("list", "1", "2", "3"));
        System.out.println("执行rpush命令!将一个或多个值插入列表尾部,从右往左插入!结果 = " + jedis.rpush("list", "4", "5", "6"));
        System.out.println("执行lrange命令!获取列表指定范围内的元素,从右往左读取!结果 = " + jedis.lrange("list", 0, -1));
        System.out.println("执行llen查询列表长度大小!结果 = " + jedis.llen("list"));
        System.out.println("执行lpop命令!移除并获取列表的第一个元素(即最右边的元素)! 结果 = " + jedis.lpop("list"));
        System.out.println("list = " + jedis.lrange("list", 0, -1));
        System.out.println("执行rpop命令!移除并获取列表最后一个元素(即最左边的元素)!结果 = " + jedis.rpop("list"));
        System.out.println("list = " + jedis.lrange("list", 0, -1));
        System.out.println("执行lindex命令!根据元素下标获取元素!结果 = " + jedis.lindex("list", 2));
        System.out.println("将一个或多个值插入到已存在的列表头部!如果列表不存在则不进行插入操作!结果 = " + jedis.lpushx("list", "a"));
        System.out.println("list = " + jedis.lrange("list", 0, -1));
        System.out.println("将一个或多个值插入到已存在的列表尾部!如果列表不存在则不进行插入操作!结果 = " + jedis.rpushx("list", "d"));
        System.out.println("list = " + jedis.lrange("list", 0, -1));
        System.out.println("执行lset命令!通过索引设置列表元素的值" + jedis.lset("list", 1, "hello"));
        System.out.println("list = " + jedis.lrange("list", 0, -1));
        System.out.println("执行ltrim命令!对一个列表进行修剪(trim),就是说,让列表只保留指定区间内的元素,不在指定区间之内的元素都将被删除。!结果 = " + jedis.ltrim("list", 0, 5));
        System.out.println("list = " + jedis.lrange("list", 0, -1));
        System.out.println("执行lrem命令!Redis Lrem 根据参数 COUNT(这里count等于2) 的值,移除列表中与参数 VALUE 相等的元素。" +
                "count > 0 : 从表头开始向表尾搜索,移除与 VALUE 相等的元素,数量为 COUNT 。" +
                "count < 0 : 从表尾开始向表头搜索,移除与 VALUE 相等的元素,数量为 COUNT 的绝对值。" +
                "count = 0 : 移除表中所有与 VALUE 相等的值。" + jedis.lrem("list", 2, "hello"));
        System.out.println("list = " + jedis.lrange("list", 0, -1));
        System.out.println("在列表的某一个具体元素前或者后插入元素" + jedis.linsert("list", BinaryClient.LIST_POSITION.AFTER, "1", "word"));
        System.out.println("list = " + jedis.lrange("list", 0, -1));
    }
}

  • 执行结果:
执行lpush命令!将一个或多个值插入到列表头部,从左往右插入!结果 = 3
执行rpush命令!将一个或多个值插入列表尾部,从右往左插入!结果 = 6
执行lrange命令!获取列表指定范围内的元素,从右往左读取!结果 = [3, 2, 1, 4, 5, 6]
执行llen查询列表长度大小!结果 = 6
执行lpop命令!移除并获取列表的第一个元素(即最右边的元素)! 结果 = 3
list = [2, 1, 4, 5, 6]
执行rpop命令!移除并获取列表最后一个元素(即最左边的元素)!结果 = 6
list = [2, 1, 4, 5]
执行lindex命令!根据元素下标获取元素!结果 = 4
将一个或多个值插入到已存在的列表头部!如果列表不存在则不进行插入操作!结果 = 5
list = [a, 2, 1, 4, 5]
将一个或多个值插入到已存在的列表尾部!如果列表不存在则不进行插入操作!结果 = 6
list = [a, 2, 1, 4, 5, d]
执行lset命令!通过索引设置列表元素的值OK
list = [a, hello, 1, 4, 5, d]
执行ltrim命令!对一个列表进行修剪(trim),就是说,让列表只保留指定区间内的元素,不在指定区间之内的元素都将被删除。!结果 = OK
list = [a, hello, 1, 4, 5, d]
执行lrem命令!Redis Lrem 根据参数 COUNT(这里count等于2) 的值,移除列表中与参数 VALUE 相等的元素。count > 0 : 从表头开始向表尾搜索,移除与 VALUE 相等的元素,数量为 COUNT 。count < 0 : 从表尾开始向表头搜索,移除与 VALUE 相等的元素,数量为 COUNT 的绝对值。count = 0 : 移除表中所有与 VALUE 相等的值。1
list = [a, 1, 4, 5, d]
在列表的某一个具体元素前或者后插入元素6
list = [a, 1, word, 4, 5, d]

2.5. 操作set
package com.acx.test;

import redis.clients.jedis.Jedis;

/**
 * set 命令
 */
public class RedisSetTest {

    public static void main(String[] args) {
        Jedis jedis = new Jedis("127.0.0.1", 6379); //默认就是操作0号数据库
        jedis.auth("123456");

        /******* 基本操作命令 *********/
        System.out.println("执行sadd命令!set集合添加一个或者多个元素!结果 = " + jedis.sadd("set01", "a", "b", "c"));
        System.out.println("执行scard命令!获取集合大小!结果 = " + jedis.scard("set01"));
        System.out.println("执行smembers命令!查询集合所有的元素!结果 = " + jedis.smembers("set01"));
        System.out.println("执行sismember命令! 查询元素是否在这个集合当中!结果 = " + jedis.sismember("set01", "a"));
        System.out.println("执行srem命令!删除结合中指定的元素!结果 = " + jedis.srem("set01", "b"));
        System.out.println("set01 = " + jedis.smembers("set01"));
        jedis.sadd("set01", "d", "e", "f", "g", "h", "i");
        System.out.println("set01 = " + jedis.smembers("set01"));

        /****** 集合操作命令 *******/
        jedis.sadd("set02", "h", "i", "hello", "word");
        System.out.println("执行sunion命令!查询集合的并集!结果 = " + jedis.sunion("set01", "set02"));
        System.out.println("执行sinter命令!查询集合的交集集!结果 = " + jedis.sinter("set01", "set02"));
        //差集结果以左边的那个集合即set01为标准
        System.out.println("执行sdiff命令!查询集合的差集!结果 = " + jedis.sdiff("set01", "set02"));
        System.out.println("执行sunionstore命令!将给定集合的并集存储在指定的集合 destination 中!结果 = " + jedis.sunionstore("set03", "set01", "set02"));
        System.out.println("set03 = " + jedis.smembers("set03"));
        System.out.println("执行sinterstore命令!将给定集合的并集存储在指定的集合 destination 中!结果 = " + jedis.sinterstore("set04", "set01", "set02"));
        System.out.println("set04 = " + jedis.smembers("set04"));
        System.out.println("执行sdiffstore命令!将给定集合的并集存储在指定的集合 destination 中!结果 = " + jedis.sdiffstore("set05", "set01", "set02"));
        System.out.println("set05 = " + jedis.smembers("set05"));
        System.out.println("执行srandmember命令!返回集合中一个或多个随机数!结果 = " + jedis.srandmember("set03"));
        System.out.println("执行srandmember命令!返回集合中一个或多个随机数!结果 = " + jedis.srandmember("set03", 3));
        System.out.println("执行spop命令!移除并返回集合中的一个随机元素!结果 = " + jedis.spop("set03"));
        System.out.println("set03 = " + jedis.smembers("set03"));
    }

}

  • 执行结果:
执行sadd命令!set集合添加一个或者多个元素!结果 = 3
执行scard命令!获取集合大小!结果 = 3
执行smembers命令!查询集合所有的元素!结果 = [c, b, a]
执行sismember命令! 查询元素是否在这个集合当中!结果 = true
执行srem命令!删除结合中指定的元素!结果 = 1
set01 = [c, a]
set01 = [h, f, i, g, c, d, e, a]
执行sunion命令!查询集合的并集!结果 = [e, d, a, word, c, hello, f, h, g, i]
执行sinter命令!查询集合的交集集!结果 = [h, i]
执行sdiff命令!查询集合的差集!结果 = [a, c, d, e, f, g]
执行sunionstore命令!将给定集合的并集存储在指定的集合 destination 中!结果 = 10
set03 = [e, d, a, word, c, hello, f, h, g, i]
执行sinterstore命令!将给定集合的并集存储在指定的集合 destination 中!结果 = 2
set04 = [h, i]
执行sdiffstore命令!将给定集合的并集存储在指定的集合 destination 中!结果 = 6
set05 = [d, f, g, c, e, a]
执行srandmember命令!返回集合中一个或多个随机数!结果 = h
执行srandmember命令!返回集合中一个或多个随机数!结果 = [c, e, g]
执行spop命令!移除并返回集合中的一个随机元素!结果 = word
set03 = [c, d, a, hello, f, h, g, i, e]

2.6. 操作zset
package com.acx.test;

import redis.clients.jedis.Jedis;

import java.util.HashMap;
import java.util.Map;

/**
 * zset 命令
 */
public class RedisZSetTest {

    public static void main(String[] args) {
        Jedis jedis = new Jedis("127.0.0.1", 6379); //默认就是操作0号数据库
        jedis.auth("123456");

        jedis.zadd("gold", 50, "zhangsan");
        Map<String, Double> map = new HashMap<>();
        map.put("lisi", 30.0);
        map.put("xiaofang", 80.0);
        map.put("xiaowei", 90.0);
        System.out.println("执行zadd命令!向有序集合添加一个或多个成员,或者更新已存在成员的分数! 结果 = " + jedis.zadd("gold", map));
        System.out.println("执行zcard命令!查询整个列表的大小!结果 = " + jedis.zcard("gold"));

        /*************  升序查询 ****************/
        System.out.println("执行zrange命令!通过索引区间返回有序集合成指定区间内的成员,升序!结果 = " + jedis.zrange("gold", 0, -1));
        System.out.println("执行zrange命令!通过索引区间返回有序集合成指定区间内的成员(包括分数),升序!结果 = " + jedis.zrangeWithScores("gold", 0, -1));
        System.out.println("执行zrangeByScore命令!通过分数区间返回有序集合指定区间内的成员!结果 = " + jedis.zrangeByScore("gold", 40, 80));
        System.out.println("执行zrangeByScore命令!通过分数区间返回有序集合指定区间内的成员(包括分数)!结果 = " + jedis.zrangeByScoreWithScores("gold", 40, 80));
        /************** 降序查询 ****************/
        System.out.println("执行zrevrange命令!返回有序集中指定区间内的成员,通过索引,分数从高到底;排列!结果 = " + jedis.zrevrange("gold", 0, -1));
        System.out.println("执行zrevrange命令!返回有序集中指定区间内的成员,通过索引,分数从高到底;排列(包括分数)!结果 = " + jedis.zrevrangeWithScores("gold", 0, -1));
        System.out.println("执行zrevrangeByScore命令!通过分数区间查询区间内的成员,降序查询!结果 = " + jedis.zrevrangeByScore("gold", 80, 40));
        System.out.println("执行zrevrangeByScore命令!通过分数区间查询区间内的成员,降序查询(包括分数)!结果 = " + jedis.zrevrangeByScoreWithScores("gold", 80, 40));

        System.out.println("执行zcount命令!查询指定分数区间内的元素个数!结果 = " + jedis.zcount("gold", 0, 80));
        //注意:zset成员的分值只能增加不能减少
        System.out.println("执行zincrby命令!元素值分值增加!结果 = " + jedis.zincrby("gold", 20, "zhangsan"));

        /************  成员相关 *************/
        System.out.println("执行zrank命令!查询指定元素的排序序号,升序!结果 = " + jedis.zrank("gold", "zhangsan"));
        System.out.println("执行zrevrank命令!查询指定元素的排序序号!降序!结果 = " + jedis.zrevrank("gold", "zhangsan"));
        System.out.println("执行zscore命令!返回有序集中,成员的分数值!结果 = " + jedis.zscore("gold", "zhangsan"));
        System.out.println("执行zrem命令!删除一个或者多个成员!结果 = "+jedis.zrem("gold", "zhangsan"));
        System.out.println("gold = " + jedis.zrange("gold", 0, -1));
    }
}

  • 执行结果:
执行zadd命令!向有序集合添加一个或多个成员,或者更新已存在成员的分数! 结果 = 3
执行zcard命令!查询整个列表的大小!结果 = 4
执行zrange命令!通过索引区间返回有序集合成指定区间内的成员,升序!结果 = [lisi, zhangsan, xiaofang, xiaowei]
执行zrange命令!通过索引区间返回有序集合成指定区间内的成员(包括分数),升序!结果 = [[[108, 105, 115, 105],30.0], [[122, 104, 97, 110, 103, 115, 97, 110],50.0], [[120, 105, 97, 111, 102, 97, 110, 103],80.0], [[120, 105, 97, 111, 119, 101, 105],90.0]]
执行zrangeByScore命令!通过分数区间返回有序集合指定区间内的成员!结果 = [zhangsan, xiaofang]
执行zrangeByScore命令!通过分数区间返回有序集合指定区间内的成员(包括分数)!结果 = [[[122, 104, 97, 110, 103, 115, 97, 110],50.0], [[120, 105, 97, 111, 102, 97, 110, 103],80.0]]
执行zrevrange命令!返回有序集中指定区间内的成员,通过索引,分数从高到底;排列!结果 = [xiaowei, xiaofang, zhangsan, lisi]
执行zrevrange命令!返回有序集中指定区间内的成员,通过索引,分数从高到底;排列(包括分数)!结果 = [[[120, 105, 97, 111, 119, 101, 105],90.0], [[120, 105, 97, 111, 102, 97, 110, 103],80.0], [[122, 104, 97, 110, 103, 115, 97, 110],50.0], [[108, 105, 115, 105],30.0]]
执行zrevrangeByScore命令!通过分数区间查询区间内的成员,降序查询!结果 = [xiaofang, zhangsan]
执行zrevrangeByScore命令!通过分数区间查询区间内的成员,降序查询(包括分数)!结果 = [[[120, 105, 97, 111, 102, 97, 110, 103],80.0], [[122, 104, 97, 110, 103, 115, 97, 110],50.0]]
执行zcount命令!查询指定分数区间内的元素个数!结果 = 3
执行zincrby命令!元素值分值增加!结果 = 70.0
执行zrank命令!查询指定元素的排序序号,升序!结果 = 1
执行zrevrank命令!查询指定元素的排序序号!降序!结果 = 2
执行zscore命令!返回有序集中,成员的分数值!结果 = 70.0
执行zrem命令!删除一个或者多个成员!结果 = 1
gold = [lisi, xiaofang, xiaowei]

2.7. 操作hash
package com.acx.test;

import redis.clients.jedis.Jedis;

import java.util.HashMap;
import java.util.Map;

/**
 * hash 命令
 */
public class RedisHashTest {

    public static void main(String[] args) {

        Jedis jedis = new Jedis("127.0.0.1", 6379); //默认就是操作0号数据库
        jedis.auth("123456");

        System.out.println("执行hset命令!将哈希表 key 中的字段 field 的值设为 value!结果 = " + jedis.hset("myhash", "name", "zhangsan"));
        Map<String, String> map = new HashMap<>();
        map.put("age", "35");
        map.put("city", "beijing");
        map.put("country", "chain");
        map.put("gold", "50");
        System.out.println("执行hmset命令!批量设置!结果 = " + jedis.hmset("myhash", map));
        System.out.println("执行hget命令!查询单个的key-value!结果 = " + jedis.hget("myhash", "name"));
        System.out.println("执行hmget命令!批量查询key-value!结果 = " + jedis.hmget("myhash", "age","city", "country", "gold"));
        System.out.println("执行hgetAll命令!查询所有的key-value!结果 = "+jedis.hgetAll("myhash"));
        System.out.println("执行hkeys命令!查询所有的key!结果 = " + jedis.hkeys("myhash"));
        System.out.println("执行hvals命令!查询所有的value!结果 = " + jedis.hvals("myhash"));
        System.out.println("执行hexists命令!判断hash中是否存在这个key!结果 = " + jedis.hexists("myhash", "name"));
        System.out.println("执行hlen命令!查询hash中key的数量!结果 = " + jedis.hlen("myhash"));
        System.out.println("执行hsetnx命令!只有在字段 field 不存在时,设置哈希表字段的值!结果 = " + jedis.hsetnx("myhash", "area", "zhaoyang"));
        System.out.println("执行hincrBy命令!为哈希表 key 中的指定字段的整数值加上增量 increment!结果 = " + jedis.hincrBy("myhash", "gold", 10));
        System.out.println("执行hdel命令!删除一个或多个哈希表字段!结果 = "+jedis.hdel("myhash", "name"));
        System.out.println("myhash = " + jedis.hgetAll("myhash"));
    }

}

  • 执行结果:
执行hset命令!将哈希表 key 中的字段 field 的值设为 value!结果 = 1
执行hmset命令!批量设置!结果 = OK
执行hget命令!查询单个的key-value!结果 = zhangsan
执行hmget命令!批量查询key-value!结果 = [35, beijing, chain, 50]
执行hgetAll命令!查询所有的key-value!结果 = {name=zhangsan, gold=50, country=chain, city=beijing, age=35}
执行hkeys命令!查询所有的key!结果 = [name, gold, country, city, age]
执行hvals命令!查询所有的value!结果 = [zhangsan, 35, 50, beijing, chain]
执行hexists命令!判断hash中是否存在这个key!结果 = true
执行hlen命令!查询hash中key的数量!结果 = 5
执行hsetnx命令!只有在字段 field 不存在时,设置哈希表字段的值!结果 = 1
执行hincrBy命令!为哈希表 key 中的指定字段的整数值加上增量 increment!结果 = 60
执行hdel命令!删除一个或多个哈希表字段!结果 = 1
myhash = {gold=60, area=zhaoyang, country=chain, city=beijing, age=35}

2.8. 操作geo
package com.acx.test;

import redis.clients.jedis.GeoCoordinate;
import redis.clients.jedis.GeoUnit;
import redis.clients.jedis.Jedis;

import java.util.HashMap;
import java.util.Map;

/**
 * geo 命令
 */
public class RedisGeoTest {

    public static void main(String[] args) {
        Jedis jedis = new Jedis("127.0.0.1", 6379); //默认就是操作0号数据库
        jedis.auth("123456");

        Map<String, GeoCoordinate> map = new HashMap<>();
        map.put("beijing", new GeoCoordinate(116.40, 39.30));
        map.put("shanghai", new GeoCoordinate(114.52, 38.05));
        map.put("nanchang", new GeoCoordinate(115.85, 28.68));
        map.put("changsha", new GeoCoordinate(112.93, 28.23));
        System.out.println("执行geoadd命令!将指定的地理空间位置(纬度、经度、名称)添加到指定的key中!结果 = " + jedis.geoadd("chain:area", map));
        System.out.println("执行geopos命令! 从key里返回所有给定位置元素的位置(经度和纬度)!结果 = " + jedis.geopos("chain:area", "beijing", "shanghai"));
        System.out.println("执行geodist命令! 返回两个给定位置之间的距离,会有0.5%的误差,单位支持M(默认是米)、KM(公里)、MI(英里)、FT(英尺)!结果 = " + jedis.geodist("chain:area", "beijing", "shanghai"));
        System.out.println("执行geodist命令! 返回距离单位km!结果 = " + jedis.geodist("chain:area", "beijing", "shanghai", GeoUnit.KM));
        System.out.println("执行georadius命令! 以给定的经纬度为中心, 找出某一半径内的元素!结果 = " + jedis.georadius("chain:area", 116.0, 38.0, 200, GeoUnit.KM));
        System.out.println("执行georadiusByMember命令! 找出位于指定范围内的元素,中心点是由给定的位置元素决定!结果 = " + jedis.georadiusByMember("chain:area", "beijing", 500, GeoUnit.KM));
    }
}

  • 执行结果:
执行geoadd命令!将指定的地理空间位置(纬度、经度、名称)添加到指定的key中!结果 = 4
执行geopos命令! 从key里返回所有给定位置元素的位置(经度和纬度)!结果 = [(116.39999896287918,39.30000117660148), (114.52000111341476,38.05000090215231)]
执行geodist命令! 返回两个给定位置之间的距离,会有0.5%的误差,单位支持M(默认是米)、KM(公里)、MI(英里)、FT(英尺)!结果 = 214421.0606
执行geodist命令! 返回距离单位km!结果 = 214.4211
执行georadius命令! 以给定的经纬度为中心, 找出某一半径内的元素!结果 = [redis.clients.jedis.GeoRadiusResponse@421faab1, redis.clients.jedis.GeoRadiusResponse@2b71fc7e]
执行georadiusByMember命令! 找出位于指定范围内的元素,中心点是由给定的位置元素决定!结果 = [redis.clients.jedis.GeoRadiusResponse@5ce65a89, redis.clients.jedis.GeoRadiusResponse@25f38edc]

2.9. 操作hyperloglog
package com.acx.test;

import redis.clients.jedis.Jedis;

/**
 * hyperloglog 命令
 */
public class RedisHyperLogLogTest {

    public static void main(String[] args) {

        Jedis jedis = new Jedis("127.0.0.1", 6379); //默认就是操作0号数据库
        jedis.auth("123456");

        System.out.println("执行pfadd命令!添加指定元素到 HyperLogLog 中!结果 = " + jedis.pfadd("read1", "a", "b", "c", "d", "a"));
        System.out.println("执行pfcount命令!返回给定 HyperLogLog 的基数估算值!结果 = " + jedis.pfcount("read1"));
        jedis.pfadd("read2", "f", "g", "a", "c", "v", "n", "m");
        System.out.println("执行pfcount命令!统计两个数据体的基数!结果 = " + jedis.pfcount("read1", "read2"));
        System.out.println("执行pfmerge命令!将多个 HyperLogLog 合并为一个 HyperLogLog!结果 = " + jedis.pfmerge("read3", "read1", "read2"));
    }
}

  • 执行结果:
执行pfadd命令!添加指定元素到 HyperLogLog 中!结果 = 1
执行pfcount命令!返回给定 HyperLogLog 的基数估算值!结果 = 4
执行pfcount命令!统计两个数据体的基数!结果 = 9
执行pfmerge命令!将多个 HyperLogLog 合并为一个 HyperLogLog!结果 = OK

2.10. 操作bitmap
package com.acx.test;

import redis.clients.jedis.Jedis;

/**
 * bitmap 命令
 */
public class RedisBitmapTest {

    public static void main(String[] args) {
        Jedis jedis = new Jedis("127.0.0.1", 6379); //默认就是操作0号数据库
        jedis.auth("123456");

        jedis.setbit("sign", 0, true);
        jedis.setbit("sign", 1, false);
        jedis.setbit("sign", 2, true);
        jedis.setbit("sign", 3, true);
        jedis.setbit("sign", 4, false);
        jedis.setbit("sign", 5, true);
        jedis.setbit("sign", 6, true);

        System.out.println("result = " + jedis.getbit("sign", 6));

        System.out.println("基数 = " + jedis.bitcount("sign"));
    }
}

  • 执行结果:
result = true
基数 = 5

2.11. 事务实现
 public static void main(String[] args) {
        Jedis jedis = new Jedis("127.0.0.1", 6379); //默认就是操作0号数据库
        jedis.auth("123456");

        Transaction multi = jedis.multi();// 开启事务
        try {
            multi.set("user1","zhangsan");
            multi.set("user2","lisi");
//            int i = 1/0; //此语句肯定会抛异常,故事务执行会取消
            multi.exec(); //执行事务
        } catch (Exception e) {
            multi.discard(); //取消/回滚事务
            e.printStackTrace();
        } finally {
            System.out.println("user1 = " + jedis.get("user1"));
            System.out.println("user2 = " + jedis.get("user2"));
            jedis.close();
        }
    }

  • 执行结果:
user1 = zhangsan
user2 = lisi

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值