【Redis学习笔记06】Jedis客户端(下)

Jedis客户端

1. 命令

1.1 Hash类型

Hash类型相信大家并不陌生,许多编程语言都有对应数据结构的实现,可能叫做哈希、字典、映射、关联数组,是相当重要的!

  • 在实际开发中非常常用
  • 在面试中也是高频考点
1.1.1 常见命令
  1. HSET命令:

语法格式:HSET key field value [field value...]
说明:设置某个key的某一个field的值为value,可以批量插入
时间复杂度:O(K),K为待插入的field数量
返回值:插入成功的field数量

127.0.0.1:6379> keys *
(empty array)
127.0.0.1:6379> HSET k1 f1 v1
(integer) 1
127.0.0.1:6379> HSET k1 f2 v2 f3 v3
(integer) 2
127.0.0.1:6379> HGETALL k1
1) "f1"
2) "v1"
3) "f2"
4) "v2"
5) "f3"
6) "v3"
  1. HGET命令:

语法格式:HGET key field
说明:获取指定key的指定field的值,如果key或者field不存在则返回nil
时间复杂度:O(1)
返回值:

  • 如果存在则返回对应值
  • 如果key或者field不存在则返回nil
127.0.0.1:6379> flushall
OK
127.0.0.1:6379> keys *
(empty array)
127.0.0.1:6379> HSET k1 f1 v1
(integer) 1
127.0.0.1:6379> HGET k1 f1
"v1"
127.0.0.1:6379> HGET k1 f2
(nil)
127.0.0.1:6379> HGET k2 f1
(nil)
  1. HEXISTE命令:

语法格式:HEXISTS key field
说明:查询某个key下是否存在某个field,如果存在返回1,如果key不存在或者field不存在返回0
时间复杂度:O(1)
返回值:

  • 如果存在,则返回1
  • 如果key或者field不存在,则返回0
127.0.0.1:6379> keys *
(empty array)
127.0.0.1:6379> HSET k1 f1 v1
(integer) 1
127.0.0.1:6379> HEXISTS k1 f1
(integer) 1
127.0.0.1:6379> HEXISTS k1 f2
(integer) 0
127.0.0.1:6379> HEXISTS k2 f1
(integer) 0
  1. HDEL命令:

语法格式:HDEL key field [field...]
说明:删除key下的一个或多个field,返回删除成功的数目
时间复杂度:O(K),K为指定的field的数量
返回值:成功删除的field数量

127.0.0.1:6379> keys *
(empty array)
127.0.0.1:6379> HSET k1 f1 v1 f2 v2 f3 v3
(integer) 3
127.0.0.1:6379> HDEL k1 f1 f3
(integer) 2
127.0.0.1:6379> HGETALL k1
1) "f2"
2) "v2"
127.0.0.1:6379> HDEL k1 f2 f3 f4
(integer) 1
127.0.0.1:6379> HGETALL k1
(empty array)
  1. HKEYS命令:

语法格式:HKEYS key
说明:展示key下全部的field字段
时间复杂度:O(N),N为field字段的数量
返回值:key下field组成的列表

127.0.0.1:6379> keys *
(empty array)
127.0.0.1:6379> HSET k1 f1 11 f2 22 f3 33
(integer) 3
127.0.0.1:6379> HKEYS k1
1) "f1"
2) "f2"
3) "f3"
  1. HVALS命令:

语法格式:HVALS key
说明:展示key下全部的field对应的value
时间复杂度:O(N),N为field字段的数量
返回值:key下field对应的value组成的列表

127.0.0.1:6379> 
127.0.0.1:6379> keys *
1) "k1"
127.0.0.1:6379> HVALS k1
1) "11"
2) "22"
3) "33"
  1. HGETALL命令:

语法格式:HGETALL key
说明:展示key下全部的field:value键值对
时间复杂度:O(N),N为field字段的数量
返回值:key下全部的field:value键值对列表

127.0.0.1:6379> keys *
1) "k1"
127.0.0.1:6379> HKEYS k1
1) "f1"
2) "f2"
3) "f3"
127.0.0.1:6379> HVALS k1
1) "11"
2) "22"
3) "33"
127.0.0.1:6379> HGETALL k1
1) "f1"
2) "11"
3) "f2"
4) "22"
5) "f3"
6) "33"

说明:上述例如HKEYS、HVALS、HGETALL等命令与KEY *类似,均小心在生产环境下使用,如果当前field数目过多,就会导致redis服务器阻塞!!!

  1. HMGET命令:

语法格式:HMGET key field [field...]
说明:查询某个key下指定的field对应的值
时间复杂度:O(K),K为指定的field的数量
返回值:返回指定的field的值对应的列表,如果没有则返回nil

127.0.0.1:6379> keys *
1) "k1"
127.0.0.1:6379> HGETALL k1
1) "f1"
2) "11"
3) "f2"
4) "22"
5) "f3"
6) "33"
127.0.0.1:6379> HMGET k1 f1 f3
1) "11"
2) "33"
  1. HLEN命令:

语法格式:HLEN key
说明:查询某个key下的field的数量
时间复杂度:O(1)
返回值:某个key下field的数量

127.0.0.1:6379> keys *
1) "k1"
127.0.0.1:6379> HGETALL k1
1) "f1"
2) "11"
3) "f2"
4) "22"
5) "f3"
6) "33"
127.0.0.1:6379> HLEN k1
(integer) 3
127.0.0.1:6379> 

  1. HSETNX命令:

语法格式:HSETNX key field value
说明:向某个key插入一对field:value键值对数据,只有原先不存在才进行插入
时间复杂度:O(1)
返回值:插入成功返回1,插入失败返回0

127.0.0.1:6379> keys *
1) "k1"
127.0.0.1:6379> HGETALL k1
1) "f1"
2) "11"
3) "f2"
4) "22"
5) "f3"
6) "33"
127.0.0.1:6379> HSETNX k1 f4 44
(integer) 1
127.0.0.1:6379> HGET k1 f4
"44"
127.0.0.1:6379> HSETNX k1 f4 55
(integer) 0
127.0.0.1:6379> HGET k1 f4
"44"
  1. HSTRLEN命令:

语法格式:HSTRLEN key field
说明:获取某个key下的某个field的value的长度(单位为字节)
时间复杂度:O(1)
返回值:返回key下某个field(字符串类型)的长度,单位为字节

127.0.0.1:6379> keys *
1) "k1"
127.0.0.1:6379> HGETALL k1
1) "f1"
2) "0"
127.0.0.1:6379> HSET k1 f2 abc
(integer) 1
127.0.0.1:6379> HSTRLEN k1 f2
(integer) 3
1.1.2 计数命令
  1. HINCRBY命令:

语法格式:HINCRBY key field increment
说明:将某个key的某个field的值+increment(increment可为负)
时间复杂度:O(1)
返回值:返回修改后的新值

127.0.0.1:6379> flushall 
OK
127.0.0.1:6379> keys *
(empty array)
127.0.0.1:6379> HSET k1 f1 11
(integer) 1
127.0.0.1:6379> HINCRBY k1 f1 20
(integer) 31
127.0.0.1:6379> HGET k1 f1
"31"
127.0.0.1:6379> HINCRBY k1 f1 -20
(integer) 11
127.0.0.1:6379> HGET k1 f1
"11"
  1. HINCRBYFLOAT命令:

语法格式:HINCRBYFLOAT key field increment
说明:将某个key的某个field的值+increment(increment可为负)
时间复杂度:O(1)
返回值:返回修改后的新值

127.0.0.1:6379> keys *
1) "k1"
127.0.0.1:6379> HGETALL k1
1) "f1"
2) "11"
127.0.0.1:6379> HINCRBYFLOAT k1 f1 0.5
"11.5"
127.0.0.1:6379> HGET k1 f1
"11.5"
127.0.0.1:6379> HINCRBYFLOAT k1 f1 -10
"1.5"
127.0.0.1:6379> HINCRBYFLOAT k1 f1 -1.5
"0"
127.0.0.1:6379> HGET k1 f1
"0"

1.2 ZSet类型

1.2.1 普通命令
  1. ZADD命令:

语法格式:ZADD key [NX | XX] [GT | LT] [CH] [INCR] score member [score member...]
说明:添加或者更新指定的元素以及与之关联的分数到有序集合中,分数应该为double类型,-inf以及+inf也是允许的
时间复杂度:O(logN)
返回值:本次添加成功的元素个数
可选项:

  • [XX | NX] : XX只更新已经存在的key,而NX如果已经存在就不更新,单纯的创建
  • [LT | GT]:LT:表示分数小于,GT:表示分数大于
  • [CH]:修改返回值的含义为新增或者更新的总个数
  • [INCR]:将分数加上指定的值
127.0.0.1:6379> ZADD k1 10 zhangsan 20 lisi 30 wangwu
3
127.0.0.1:6379> ZRANGE k1 0 -1 withscores
zhangsan
10
lisi
20
wangwu
30
127.0.0.1:6379> ZADD k1 NX 50 wangwu
0
127.0.0.1:6379> ZRANGE k1 0 -1 withscores
zhangsan
10
lisi
20
wangwu
30
127.0.0.1:6379> ZADD k1 NX 50 zhaoliu
1
127.0.0.1:6379> ZRANGE k1 0 -1 withscores
zhangsan
10
lisi
20
wangwu
30
zhaoliu
50
127.0.0.1:6379> ZADD k1 XX 70 laoqi
0
127.0.0.1:6379> ZADD k1 XX 60 zhaoliu
0
127.0.0.1:6379> ZRANGE k1 0 -1 withscores
zhangsan
10
lisi
20
wangwu
30
zhaoliu
60
127.0.0.1:6379> ZADD k1 XX CH 70 zhaoliu
1
127.0.0.1:6379> ZRANGE k1 0 -1 withscores
zhangsan
10
lisi
20
wangwu
30
zhaoliu
70
  1. ZCARD命令:

语法格式:ZCARD key
说明:返回指定有序集合的元素个数
时间复杂度:O(1)
返回值:有序集合中的元素个数

127.0.0.1:6379> ZADD k1 10 zhangsan 20 lisi 30 wangwu
3
127.0.0.1:6379> ZRANGE k1 0 -1 withscores
zhangsan
10
lisi
20
wangwu
30
127.0.0.1:6379> ZCARD k1
3
  1. ZCOUNT命令:

语法格式:ZCOUNT key min max
说明:返回分数在min以及max区间的元素个数,默认情况下min,max均包含,(min max表示(min, max],(min (max表示(min, max)
时间复杂度:O(log(N))
返回值:符合分数区间的元素个数

127.0.0.1:6379> keys *

127.0.0.1:6379> ZADD k1 10 zhangsan 20 lisi 30 wangwu
3
127.0.0.1:6379> ZRANGE k1 0 -1 withscores
zhangsan
10
lisi
20
wangwu
30
127.0.0.1:6379> ZCOUNT k1 10 30
3
127.0.0.1:6379> ZCOUNT k1 (10 30
2
127.0.0.1:6379> ZCOUNT k1 (10 (30
1
  1. ZRANGE命令:

语法格式:ZRANGE key start stop [withscores]
说明:返回区间为[start, stop]内的元素列表,升序排列,withscores可以携带分数返回
时间复杂度:(O(logN + M))
返回值:指定区间的元素列表

127.0.0.1:6379> keys *

127.0.0.1:6379> ZADD k1 10 one 20 two 30 three
3
127.0.0.1:6379> ZRANGE k1 0 -1 
one
two
three
127.0.0.1:6379> ZRANGE k1 0 -1 withscores
one
10
two
20
three
30
  1. ZREVRANGE命令:

语法格式:ZREVRANGE key start stop [withscores]
说明:返回区间为[start, stop]内的元素列表,降序排列,withscores可以携带分数返回
时间复杂度:O(log(N) + M)
返回值:指定区间的元素列表

127.0.0.1:6379> keys *

127.0.0.1:6379> ZADD k1 10 zhangsan 20 lisi 30 wangwu
3
127.0.0.1:6379> ZREVRANGE k1 0 -1
wangwu
lisi
zhangsan
127.0.0.1:6379> ZREVRANGE k1 0 -1 withscores
wangwu
30
lisi
20
zhangsan
10
  1. ZRANGEBYSCORE命令:

语法格式:ZRANGEBYSCORE key min max [withscores]
说明:返回分数区间在[min, max]之间的元素列表
时间复杂度:O(log(N) + M)
返回值:指定区间内元素列表

127.0.0.1:6379> keys *
k1
127.0.0.1:6379> flushall
OK
127.0.0.1:6379> ZADD k1 10 zhangsan 20 lisi 30 wangwu
3
127.0.0.1:6379> ZRANGEBYSCORE k1 20 30 withscores
lisi
20
wangwu
30
  1. ZPOPMAX命令:

语法格式:ZPOPMAX key [count]
说明:删除并返回分数最高的count个元素
时间复杂度:(O(logN * M)) ,Redis在此处没有优化
返回值:分数和元素列表

127.0.0.1:6379> keys *

127.0.0.1:6379> ZADD k1 10 zhangsan 20 lisi 30 wangwu
3
127.0.0.1:6379> ZPOPMAX k1 
wangwu
30
127.0.0.1:6379> ZPOPMAX k1 2
lisi
20
zhangsan
10
  1. BZPOPMAX命令:

语法格式:BZPOPMAX key [key...] timeout
说明:BZPOPMAX的阻塞版本,监听多个key的有序集合,timeout为超时时间
时间复杂度:O(logN)
返回值:key以及元素以及对应分数
:::success
ZPOPMIN、BZPOPMIN与上述类似
:::

  1. ZRANK命令:

语法格式:ZRANK key member
说明:返回member对应的排名(升序)
时间复杂度:O(logN)
返回值:member升序排名

127.0.0.1:6379> keys *

127.0.0.1:6379> ZADD k1 10 zhangsan 20 lisi 30 wangwu
3
127.0.0.1:6379> ZRANK k1 wangwu
2
127.0.0.1:6379> ZRANGE k1 0 -1 withscores
zhangsan
10
lisi
20
wangwu
30
  1. ZREVRANK命令:

语法格式:ZREVRANK key member
说明:返回member对应的排名(降序)
时间复杂度:(OlogN)
返回值:member降序排名

127.0.0.1:6379> keys *

127.0.0.1:6379> ZADD 10 zhangsan 20 lisi 30 wangwu
ERR syntax error

127.0.0.1:6379> ZADD k1 10 zhangsan 20 lisi 30 wangwu
3
127.0.0.1:6379> ZRANGE k1 0 -1 withscores
zhangsan
10
lisi
20
wangwu
30
127.0.0.1:6379> ZREVRANK k1 wangwu
0
  1. SCORE命令:

语法格式:ZSCORE key
说明:返回指定元素的分数
时间复杂度:O(1)
返回值:memebr对应分数

127.0.0.1:6379> keys *
k1
127.0.0.1:6379> ZRANGE k1 0 -1 withscores
zhangsan
10
lisi
20
wangwu
30
127.0.0.1:6379> ZSCORE k1 wangwu
30
1.2.2 Zset内部编码方式

Zset内部编码方式主要有以下两种:

  1. ziplist:压缩列表,当有序集合中存储元素数量较少,不超过zset-max-ziplist-entries配置项(默认128),同时每个元素的大小不超过zset-max-ziplist-value配置(默认为64)则使用ziplist进行存储,目的是为了节省内存空间
  2. skiplist:跳表,当存储元素个数或者大小不满足ziplist条件时,就会转换为skiplist进行实现

1)当元素个数较少并且单个元素占用空间不高的情况

127.0.0.1:6379> keys *
(empty array)
127.0.0.1:6379> zadd k1 10 zhangsan
(integer) 1
127.0.0.1:6379> OBJECT ENCODING k1
"ziplist"

2)当单个元素占用空间过高的情况:

127.0.0.1:6379> zadd k2 32 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
(integer) 1
127.0.0.1:6379> OBJECT ENCODING k2
"skiplist"

关于跳表:
简单来说,跳表就是一个"复杂链表",查询元素的时间复杂度可以达到O(logN),相比于树形结构(平衡二叉树),跳表的好处是可以支持范围查询

1.2.3 Zset应用场景

Zset作为一个有序集合,最重要的应用场景就是作为 **“排行榜系统”,**例如:

  1. 微博热榜
  2. 游戏天梯榜
  3. 成绩排行榜

关键就在于需要快速对用于排行的"分数"实时更新,而Zset一些命令例如:ZSCOREZRANKZINCRBY能够快速修改信息以及重新排名
微博热榜:
微博热榜相对于游戏天梯榜更为复杂,因为游戏天梯榜依据玩家排位分作为score,但是微博热榜中的热度值score有多方面影响因素,例如:点赞数、转发量、浏览量、评论量,我们可以根据不同的维度计算出不同的分数score,然后依据权重值的不同借助ZINTERSTORE等命令进行加权处理进行集合间运算,后续也就可以依据所得的分数score进行排序

1.3 Redis其余数据类型

上面我们介绍了String、List、Hash、Set、Zset等五种常见的数据结构,但是Redis除此之外还提供了另外的数据结构,但是这些数据结构只是针对某些特殊场景适用,应用广泛性远远不及上述五种数据结构

1.3.1 stream类型

steam类型可以用作模拟实现事件传播机制
所谓事件:
事件其实大家并不陌生:

  • 对于像epoll等IO多路复用模型就是借助了事件,例如当网卡上有可读可写的数据时,就会借助事件回调机制通知应用程序进行处理
  • 在前端JS领域,onClick="doClick()"等点击事件也使用到了事件概念

在Redis中的stream可以看做是一个"阻塞队列",是用来实现"消息队列"的重要基础,可以看做是"BLPOP","BRPOP"的增强版本。

1.3.2 Geospatial类型

是Redis内部的一个存储地理位置的数据结构,即存储坐标信息(经纬度)
Geospatial类型常常用于地图等功能中,可以给定一个坐标和一个半径,查找附近范围内存储的点信息

1.3.3 HyperLogLog类型

应用场景:估算集合中的元素个数
前面我们介绍过Set类型一大重要应用场景就是进行"UV"统计,但是如果用户量个数非常庞大,比如有1亿用户,那么每个用户存储一个userId(8字节)就是8亿字节=0.8GB,但是HyperLogLog可以只最多用12KB的内存进行存储,关键就在于HyperLogLog不存储元素本身,而是借助 “**位运算” **操作存储数据特征,这样一来就能够在新增元素的同时判断该元素是否新增过(存在误差)
HyperLogLog VS Set
HyperLogLog:

  • 优点:占用存储空间小
  • 缺点:无法给出具体的存储元素,存在误差

Set:

  • 优点:内部保存了具体的元素,且无误差
  • 缺点:占用存储空间相对较大
1.3.4 Bitmaps类型

位图:本质上还是一个集合,可以看做是Set类型对于整型所做的特化版本,目的依旧是为了节省空间,例如需要存储元素10,使用位图就是00000000 00000000 00000010 00000000
Bitmaps VS HyperLogLog

  • bitmaps不仅仅存储元素特征,也存储元素具体类型(占用空间更大)
  • bitmaps针对整型,而HyperLogLog可以针对字符串类型
1.3.5 Bitfields类型

Bitfields类似于C语言结构体中的位段:可以理解为是一串二进制序列(字节数组),同时可以对于其中的几位进行算数、读取、修改操作,目的仍旧是节省空间!

2. Java客户端操作redis

Java生态丰富,自定义的客户端非常多,常见的有Jedis、Lettuce、以及Spring整合后的RedisTemplate,但是对于初学者而言,从Jedis开始入门学习是非常容易上手的,因为Jedis中的API与原生Redis命令高度一致。

2.1 引入Jedis依赖

此处引入如下依赖:

  • Jedis:Java操作Redis客户端
  • Junit:方便编写单元测试
<!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
<dependency>
  <groupId>redis.clients</groupId>
  <artifactId>jedis</artifactId>
  <version>4.4.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
</dependency>

2.2 配置Xshell端口转发

  1. 操作步骤:1. 打开Xshell点击属性 => 2. 配置SSH隧道 => 3. 配置如下端口转发内容

image.png

  1. 打开windows cmd程序输入:netstat -ano | findstr 8888如果观察如下

image.png

  1. 确保redis.conf配置中设置protect-mode为no以及bind为0.0.0.0

2.3 编写Demo

使用Jedis的步骤如下:

  1. 创建JedisPool连接池对象(配置redis服务器所在IP地址+端口号)
  2. 从JedisPool连接池中取出连接对象,并操作其中提供的API方法
  3. 解析响应内容
/**
 * 测试Redis连通性
 * @author 米饭好好吃
 */
@Test
public void testPing() {
    // 1. 创建JedisPool
    JedisPool pool = new JedisPool("tcp://127.0.0.1:8888");
    // 2. 获取连接对象
    try(Jedis jedis = pool.getResource();) {
        // 设置密码(如果有)
        jedis.auth("xxxxxx");
        // 3. 调用API-ping
        String pong = jedis.ping();
        // 4. 解析响应结果
        System.out.println(pong);
    }
}

2.4 测试Hash类型

对于Redis中Hash类型,常见的命令有:hset、hget、hmset、hmget、hexists、hdel、hkeys、hvals、hgetall、hincrby、hincrbyfloat…
下面我们简单介绍一些命令如何使用Jedis客户端调用:

  1. 测试HSET、HGET命令:
/**
 * 测试Redis中的Hash类型
 * @author 米饭好好吃
 */
public class TestHash {
    private JedisPool pool;

    @Before
    public void init() {
        pool = new JedisPool("tcp://127.0.0.1:8888");
    }

    @Test
    public void testHSETAndHGET() {
        // 1. 获取到Jedis连接对象
        try(Jedis jedis = pool.getResource();) {
            // 设置密码(如果有的话)
            // jedis.auth("xxxxxx");
            // 2. 清空数据库
            jedis.flushDB();
            // 3. 测试HSET、HGET命令
            jedis.hset("k1", "f1", "11");
            String res = jedis.hget("k1", "f1");
            System.out.println("k1 f1: " + res);
        }
    }
}

  1. 测试HMSET、HMGET命令:
/**
 * 测试HMSET、HMGET命令
 */
@Test
public void testHMSETAndHMGET() {
    // 1. 获取Jedis连接对象
    try (Jedis jedis = pool.getResource();) {
        // 设置密码(如果有的话)
        // jedis.auth("xxxxxx");
        // 2. 清空数据库
        jedis.flushDB();
        // 3. 测试HMSET、HMGET命令
        Map<String, String> map = new HashMap<>();
        map.put("f1", "11");
        map.put("f2", "22");
        map.put("f3", "33");
        jedis.hmset("k1", map);
        List<String> list = jedis.hmget("k1", "f1", "f2", "f3");
        System.out.println("list: " + list);
    }
}
  1. 测试HEXISTS、HDEL命令:
/**
 * 测试HEXISTS以及HDEL命令
 */
@Test
public void testHEXISTSAndHDEL() {
    // 1. 获取Jedis连接对象
    try (Jedis jedis = pool.getResource();) {
        // 设置密码(如果有的话)
        // jedis.auth("xxxxxx");
        // 2. 清空数据库
        jedis.flushDB();
        // 3. 测试HEXISTS、HDEL命令
        jedis.hset("k1", "f1", "11");
        jedis.hset("k1", "f2", "22");
        jedis.hset("k1", "f3", "33");
        boolean exists = jedis.hexists("k1", "f1");
        System.out.println("exists: " + exists);
        jedis.hdel("k1", "f1");
        exists = jedis.hexists("k1", "f1");
        System.out.println("exists: " + exists);
    }
}
  1. 测试HKEYS、HVALS、HGELALL命令:
/**
 * 测试HKEYS、HVALS、HGETALL命令
 */
@Test
public void testHKEYSAndHVALSAndHGETALL() {
    // 1. 获取Jedis连接对象
    try (Jedis jedis = pool.getResource();) {
        // 设置密码(如果有的话)
        // jedis.auth("xxxxxx");
        // 2. 清空数据库
        jedis.flushDB();
        // 3. 测试HKEYS、HVALS、HGETALL命令
        jedis.hset("k1", "f1", "11");
        jedis.hset("k1", "f2", "22");
        jedis.hset("k1", "f3", "33");
        Set<String> hKeys = jedis.hkeys("k1");
        List<String> hValues = jedis.hvals("k1");
        Map<String, String> map = jedis.hgetAll("k1");
        System.out.println("hkeys: " + hKeys);
        System.out.println("hvals: " + hValues);
        System.out.println("hgetalls: " + map);
    }
}
  1. 测试HLEN命令:
/**
 * 测试HLEN命令
 */
@Test
public void testHLEN() {
    // 1. 获取Jedis连接对象
    try (Jedis jedis = pool.getResource();) {
        // 设置密码(如果有的话)
        // jedis.auth("xxxxxx");
        // 2. 清空数据库
        jedis.flushDB();
        // 3. 测试HLEN命令
        jedis.hset("k1", "f1", "11");
        jedis.hset("k1", "f2", "22");
        jedis.hset("k1", "f3", "33");
        long len = jedis.hlen("k1");
        System.out.println("len: " + len);
    }
}
  1. 测试HINCRBY命令:
/**
 * 测试HINCRBY命令
 */
@Test
public void testHINCRBY() {
    // 1. 获取Jedis连接对象
    try (Jedis jedis = pool.getResource();) {
        // 设置密码(如果有的话)
        // jedis.auth("xxxxxx");
        // 2. 清空数据库
        jedis.flushDB();
        // 3. 测试HINCR命令
        jedis.hset("k1", "f1", "10");
        jedis.hincrBy("k1", "f1", 5);
        String res = jedis.hget("k1", "f1");
        System.out.println("k1 f1:  " + res);
    }
}

2.5 测试ZSet类型

对于Redis中ZSet类型,常见的命令有:zadd、zrange、zscore、zrank、zrem、zpopmax、zpopmin、zcard、zinterstore、zunionstore、zdiffstore…
下面我们简单介绍一些命令如何使用Jedis客户端调用:

  1. 测试ZADD、ZRANGE命令:
/**
 * 测试ZADD、ZRANGE命令
 */
@Test
public void testZADDAndZRANGE() {
    // 1. 获取Jedis连接对象
    try (Jedis jedis = pool.getResource();) {
        // 设置密码(如果有的话)
        // jedis.auth("xxxxxx");
        // 2. 清空数据库
        jedis.flushDB();
        // 3. 测试ZADD、ZRANGE命令
        jedis.zadd("k1", 10, "zhangsan");
        jedis.zadd("k1", 20, "lisi");
        jedis.zadd("k1", 30, "wangwu");
        List<String> list = jedis.zrange("k1", 0, -1);
        System.out.println("list: " + list);
        List<Tuple> tuples = jedis.zrangeWithScores("k1", 0, -1);
        System.out.println("tuples: " + tuples);
    }
}
  1. 测试ZSCORE、ZRANK命令:
/**
 * 测试ZRANK、ZSCORE命令
 */
@Test
public void testZSCOREAndZRANK() {
    // 1. 获取Jedis连接对象
    try (Jedis jedis = pool.getResource();) {
        // 设置密码(如果有的话)
        // jedis.auth("xxxxxx");
        // 2. 清空数据库
        jedis.flushDB();
        // 3. 测试ZSCORE、ZRANK命令
        jedis.zadd("k1", 10, "zhangsan");
        jedis.zadd("k1", 20, "lisi");
        jedis.zadd("k1", 30, "wangwu");
        Double score = jedis.zscore("k1", "lisi");
        System.out.println("score: " + score);
        Long rank = jedis.zrank("k1", "wangwu");
        System.out.println("rank: " + rank);
    }
}
  1. 测试ZREM、ZCARD命令:
/**
 * 测试ZCARD、ZREM命令
 */
@Test
public void testZCARDAndZREM() {
    // 1. 获取Jedis连接对象
    try (Jedis jedis = pool.getResource();) {
        // 设置密码(如果有的话)
        // jedis.auth("xxxxxx");
        // 2. 清空数据库
        jedis.flushDB();
        // 3. 测试ZCARD命令
        jedis.zadd("k1", 10, "zhangsan");
        jedis.zadd("k1", 20, "lisi");
        jedis.zadd("k1", 30, "wangwu");
        long size = jedis.zcard("k1");
        System.out.println("size: " + size);
        jedis.zrem("k1", "zhangsan", "lisi");
        size = jedis.zcard("k1");
        System.out.println("size: " + size);
    }
}
  1. 测试ZINTERSTORE命令:
/**
 * 测试ZINTERSTORE命令
 */
@Test
public void testZINTERSTORE() {
    // 1. 获取Jedis连接对象
    try (Jedis jedis = pool.getResource();) {
        // 设置密码(如果有的话)
        // jedis.auth("xxxxxx");
        // 2. 清空数据库
        jedis.flushDB();
        // 3. 测试ZINTERSTORE命令
        jedis.zadd("k1", 10, "zhangsan");
        jedis.zadd("k2", 20, "zhangsan");
        jedis.zinterstore("k3", "k1", "k2");
        List<Tuple> tuples = jedis.zrangeWithScores("k3", 0, -1);
        System.out.println("tuples: " + tuples);
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/694967.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

pytorch-数据增强

目录 1. Flip翻转2. Rotate旋转3. scale缩放4. crop裁剪5. 总结6. 完整代码 1. Flip翻转 上图中做了随机水平翻转和随机垂直翻转&#xff0c;翻转完成后转化成tensor 2. Rotate旋转 上图中作了2次旋转第一次旋转角度在-15<0<15范围内&#xff0c;随机出一个角度&#xf…

Java SE(Java Platform, Standard Edition)

Java SE&#xff08;Java Platform, Standard Edition&#xff09; 是Java平台的一个版本&#xff0c;面向桌面应用程序、服务器和嵌入式环境。Java SE提供了开发和运行Java应用程序的基础API&#xff08;Application Programming Interface&#xff0c;应用程序编程接口&…

Java 编译报错:找不到符号? 手把手教你排查解决!

Java 编译报错&#xff1a;找不到符号&#xff1f; 手把手教你排查解决&#xff01; 在 Java 开发过程中&#xff0c;我们经常会遇到编译器抛出 "找不到符号" 错误。这个错误提示意味着编译器无法在它所理解的范围内找到你所引用的类、变量或方法。这篇文章将带你一步…

Spring Security 应用详解

一、 集成SpringBoot 1.1 Spring Boot 介绍 Spring Boot 是一套 Spring 的快速开发框架&#xff0c;基于 Spring 4.0 设计&#xff0c;使用 Spring Boot 开发可以避免一些繁琐的工程 搭建和配置&#xff0c;同时它集成了大量的常用框架&#xff0c;快速导入依赖包&#xff0…

html--宇航员404

<!doctype html> <html> <head> <meta charset"utf-8"> <title>太空404</title><style> html {margin: 0;padding: 0;background-color: white; }body, html {width: 100%;height: 100%;overflow: hidden; }#svgContainer…

数据结构(C):二叉树前中后序和层序详解及代码实现及深度刨析

目录 &#x1f31e;0.前言 &#x1f688;1.二叉树链式结构的代码是实现 &#x1f688;2.二叉树的遍历及代码实现和深度刨析代码 &#x1f69d;2.1前序遍历 ✈️2.1.1前序遍历的理解 ✈️2.1.2前序代码的实现 ✈️2.1.3前序代码的深度解剖 &#x1f69d;2.2中序遍历 ✈…

【QT5】<总览五> QT多线程、TCP/UDP

文章目录 前言 一、QThread多线程 二、QT中的TCP编程 1. TCP简介 2. 服务端程序编写 3. 客户端程序编写 4. 服务端与客户端测试 三、QT中的UDP编程 1. UDP简介 2. UDP单播与广播程序 前言 承接【QT5】&#xff1c;总览四&#xff1e; QT常见绘图、图表及动画。若存在…

开启数字化校园解决方案,实现教育智能化

现代社会的教育面临诸多挑战&#xff0c;如何提高教育质量&#xff0c;实现教育智能化成为了当务之急。数字化校园解决方案应运而生&#xff0c;为学校提供了全新的教学模式和管理方式。本文将介绍数字化校园解决方案的重要性&#xff0c;以及如何开启数字化校园&#xff0c;实…

【端午安康,给大家讲个“网络”故事,深刻一下!】

牛马我&#x1f434;上周又挨锤了&#xff0c; 网络是不稳定的&#xff0c;博学多知的你可能知道&#xff0c;可能不知道。但假如没亲身经历过&#xff0c;知不知道都不深刻&#xff0c;牛马踩了个网络的坑&#xff0c;深刻了&#xff0c;这里分享下&#xff0c; 一个真相 无…

【Python报错】已解决ImportError: cannot import name ‘triu’ from ‘scipy.linalg’

成功解决“ImportError: cannot import name ‘triu’ from ‘scipy.linalg’”错误的全面指南 在Python编程中&#xff0c;尤其是在使用scipy这个科学计算库时&#xff0c;可能会遇到ImportError错误&#xff0c;提示无法从scipy.linalg模块中导入名为triu的函数。这个错误通…

深入JVM:线上内存泄漏问题诊断与处理

文章目录 深入JVM&#xff1a;线上内存泄漏问题诊断与处理一、序言二、内存泄漏概念三、内存泄漏环境模拟四、内存泄漏诊断与解决1、步骤一&#xff1a;获取堆内存快照文件&#xff08;1&#xff09;获取正在运行程序dump文件&#xff08;2&#xff09;获取已终止程序dump文件 …

HP Laptop 14s-fr1xxx原厂oem预装Win11系统ISO镜像下载

惠普星青春版14s-fr1xxx笔记本电脑原装出厂Windows11系统安装包&#xff0c;恢复出厂开箱状态一模一样 链接&#xff1a;https://pan.baidu.com/s/11Qe5XgCmH3emIVEpvoKclg?pwdm1qe 提取码&#xff1a;m1qe 适用型号&#xff1a;14s-fr1xxx 14s-fr0001AU、14s-fr0002AU、…

VMware Fusion 如何增加linux硬盘空间并成功挂载

文章目录 0. 前言1. 增加硬盘空间2. 硬盘分区2.1 查看硬盘2.2 分区2.3 格式化2.4 挂载 3. 参考 0. 前言 如果发现虚拟机分配的硬盘不足&#xff0c;需要增加硬盘空间。本文教给大家如何增加硬盘空间并成功挂载。 查看当前硬盘使用情况&#xff1a; df -h可以看到&#xff0c…

sqli-labs 靶场 less-7 第七关详解:OUTFILE注入与配置

SQLi-Labs是一个用于学习和练习SQL注入漏洞的开源应用程序。通过它&#xff0c;我们可以学习如何识别和利用不同类型的SQL注入漏洞&#xff0c;并了解如何修复和防范这些漏洞。Less 7 SQLI DUMB SERIES-7判断注入点 进入页面中&#xff0c;并输入数据查看结果。 发现空数据提…

求宇文玥在水下的浮力和赵丽颖捞他的时间

关注微信公众号 数据分析螺丝钉 免费领取价值万元的python/java/商业分析/数据结构与算法学习资料 2024年汉东省在达康书记的带领下率先实现高考试点改革。为让更多的考生能提升对他们的理解和记忆&#xff0c;把电视剧的场景融入考试题目中。确保学生看一遍就懂&#xff0c;想…

debian12安装时分区方案

一、初次尝试 一共设置了4个分区&#xff0c;其中根目录/分区46G&#xff0c;swap分区10G&#xff08;电脑内存为6G&#xff09;&#xff0c;/boot分区200M&#xff0c;/home分区55G。系统安装之后的实际占有情况为&#xff1a; 二、调整后情况 一共设置了4个分区&#xff0c…

基于R语言BIOMOD2 及机器学习方法的物种分布模拟与案例分析

原文链接&#xff1a;基于R语言BIOMOD2 及机器学习方法的物种分布模拟与案例分析https://mp.weixin.qq.com/s?__bizMzUzNTczMDMxMg&mid2247606139&idx4&snf94ec30bfb5fa7ac0320403d49db3b66&chksmfa821e9ccdf5978a44a9ba96f6e04a121c0bbf63beea0940b385011c0b…

Spring运维之boo项目表现层测试匹配响应执行状态响应体JSON和响应头

匹配响应执行状态 我们创建了测试环境 而且发送了虚拟的请求 我们接下来要进行验证 验证请求和预期值是否匹配 MVC结果匹配器 匹配上了 匹配失败 package com.example.demo;import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Auto…

【网络教程】Iptables官方教程-学习笔记7-简单理解IPTABLES规则的作用流程

前面学习了IPTABLES的所有功能介绍后&#xff0c;一个Linux设备里的IPTABLES规则集是如何运行的&#xff0c;这里简单做个介绍。 在Linux设备里输入"iptables -nvl",得到该设备的所有防火墙规则&#xff0c;得到的结果中可以看到这个设备防火墙里所有的链以及链里的…

2024年CKA模拟系统制作 | step-by-step | 1、基础环境准备

目录 一、软件环境 二、虚拟网络环境准备 1、编辑虚拟网络 2、网络设置 三、新建虚拟主机 1、新建目录 2、新建虚拟主机 四、系统安装 1、装载系统镜像 2、开启虚拟机 3、选择语言 4、键盘选择 5、网络配置 6、代理设置 7、设置软件源 8、存储设置 9、名称设置 …