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

news2024/9/20 9:06:50

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.coloradmin.cn/o/1807583.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Django API开发实战:前后端分离、Restful风格与DRF序列化器详解

系列文章目录 Django入门全攻略&#xff1a;从零搭建你的第一个Web项目Django ORM入门指南&#xff1a;从概念到实践&#xff0c;掌握模型创建、迁移与视图操作Django ORM实战&#xff1a;模型字段与元选项配置&#xff0c;以及链式过滤与QF查询详解Django ORM深度游&#xff…

NLP实战入门——文本分类任务(TextRNN,TextCNN,TextRNN_Att,TextRCNN,FastText,DPCNN,BERT,ERNIE)

本文参考自https://github.com/649453932/Chinese-Text-Classification-Pytorch?tabreadme-ov-file&#xff0c;https://github.com/leerumor/nlp_tutorial?tabreadme-ov-file&#xff0c;https://zhuanlan.zhihu.com/p/73176084&#xff0c;是为了进行NLP的一些典型模型的总…

Day 25 二叉树的终止

450.删除二叉搜索树中的节点 不理解用tmp保存root节点&#xff0c;然后删除&#xff1f;rootroot->right不会覆盖吗&#xff1f; 需要考虑要删除的节点是不是叶子节点&#xff0c;有无左右孩子 有左右孩子的话&#xff0c;需要将左孩子节点移动到右孩子节点的左面节点的左…

Python | Leetcode Python题解之第142题环形链表II

题目&#xff1a; 题解&#xff1a; # Definition for singly-linked list. # class ListNode: # def __init__(self, x): # self.val x # self.next Noneclass Solution(object):def detectCycle(self, head):""":type head: ListNode:…

element-plus 的el-scrollbar滚动条组件

el-scrollbar组件可以替换原生的滚动条&#xff0c;可以设置出现滚动条的高度&#xff0c;若无设置则根据容器自适应。 通过使用 setScrollTop 与 setScrollLeft 方法&#xff0c;可以手动控制滚动条滚动。 scroll 滚动条的滚动事件&#xff0c;会返回滚动条当前的位置。 &l…

机器学习--生成式模型和判别式模型的具体分析

文章目录 生成式模型和判别式模型的具体分析生成式模型定义工作原理优点缺点常见模型 判别式模型 总结生成式模型判别式模型 生成式模型和判别式模型的具体分析 生成式模型和判别式模型在机器学习中有着不同的目标、应用场景和性能特点。以下将详细分析它们的定义、工作原理、…

《庆余年》角色穿越高考:谁将笑傲现代考场?

一、引言 《庆余年》是一部以古代中国为背景的权谋小说&#xff0c;其角色们各具特色&#xff0c;聪明才智、武艺高强、忠诚耿直等特质使得他们在古代世界中游刃有余。然而&#xff0c;如果我们将这些角色置于现代高考的背景之下&#xff0c;他们将如何面对这一挑战&#xff1…

C# WPF入门学习主线篇(二十)—— 资源和样式

C# WPF入门学习主线篇&#xff08;二十&#xff09;—— 资源和样式 欢迎来到C# WPF入门学习系列的第二十篇。在前面的章节中&#xff0c;我们探讨了布局管理及各种控件的使用。本篇博客将重点介绍WPF中的资源&#xff08;Resource&#xff09;和样式&#xff08;Style&#xf…

抛弃昂贵BI,企业仍可低成本实现数据分析

有的读者看完《BI工具选型不入坑&#xff0c;你要这么选》这篇文章就陷入迷茫了&#xff0c;我要做企业级数据分析&#xff0c;看过去各家产品都各有千秋&#xff0c;实在难以抉择&#xff0c;或者已经选了仍是纠结不已。 这里我抛出另一种思路&#xff1a;如果不用BI&#xf…

MySQL 5.7详细下载安装配置教程(MySQL 5.7安装包)_mysql5.7的安装教程

记录MySQL 5.7 的下载安装教程&#xff0c;并提供了Mysql 安装包 &#xff0c;以下是详细下载安装过程。 一、下载Mysql安装包 网盘下载&#xff1a; 下载MySQL 5.7安装包&#xff0c;网盘下载地址&#xff1a;点击此处直接下载 官网下载&#xff1a; 进入官网&#xff0c…

如何稳定高效地进行 TiDB 数据导入导出?

对于在数据库行业中摸爬滚打多年的老鸟 DBA 来说&#xff0c;TiDB 可是一点也不陌生&#xff0c;作为 PingCAP 公司自主研发的真开源分布式数据库&#xff0c;其先进的设计理念以及丰富的生态工具&#xff0c;可算得上是业界自主创新和性能领先的代名词。 TiDB 是谁&#xff1…

《Brave New Words 》3.4 最重要的学科领域

Part III Empowering the Next Innovators 第三部分 赋能下一代创新者 The Most Important Subject-Matter Domain to Master 最重要的学科领域 In the world of education, it’s crucial for developers to field-test their ideas. Essentially, it means taking our educat…

LabVIEW进行图像拼接的实现方法与优化

在工业检测和科研应用中&#xff0c;对于大尺寸物体的拍摄需要通过多次拍摄后进行图像拼接。LabVIEW 作为强大的图形化编程工具&#xff0c;能够实现图像拼接处理。本文将详细介绍LabVIEW进行图像拼接的实现方法、注意事项和提高效率的策略。 图像拼接的实现方法 1. 图像采集…

前端UI框架Element Plus 和 Ant Design Vue哪个好

Element Plus 和 Ant Design Vue 都是基于 Vue.js 的 UI 组件库&#xff0c;它们具备一系列可复用的组件和丰富的功能&#xff0c;并且是当前国内主流的两个 UI 组件库。 &#xff08;1&#xff09;Element Plus 是饿了么前端团队推出的开源项目&#xff0c;是对 Element UI 的…

基于Python + Flask+ Mysq实现简易留言板

使用Python Flask Mysql实现简易留言板&#xff0c;包括网友编辑留言、修改留言&#xff0c;删除留言、分页显示四大功能。 写出留言板建设过程&#xff0c;包括开发使用工具、留言板模块设计、数据库设计、页面设计、关键技术。 留言板建设过程总结 一&#xff0e;开发使用…

RapidMiner数据挖掘4 —— 决策树

0. 序章 0.1 文本说明 所有应用程序操作的名称和编程说明都以黄色背景书写&#xff0c;问题以蓝色背景书写&#xff0c;以方便他们在文本中识别。 在整个课程中&#xff0c;请逐步遵循所有说明&#xff0c;并确保获得预期结果&#xff0c;然后再继续下一部分或问题。 通过在Ub…

文刻ai工具跟绘唐AI工具有什么区别

文刻AI工具和绘唐AI工具是两种不同的人工智能工具。点击查看 文刻AI工具是一种自然语言处理工具&#xff0c;可以用于生成、修改和校对文本。它可以帮助用户更高效地写作&#xff0c;提供词汇和语法建议&#xff0c;检查拼写和语法错误&#xff0c;并提供自动补全和自动纠正功…

网络安全难学吗?2024该怎么系统学习网络安全?

学习网络安全需要循序渐进&#xff0c;由浅入深。很多人对网络安全进行了解以后&#xff0c;就打算开始学习网络安全&#xff0c;但是又不知道怎么去系统的学习。 网络安全本身的知识不难&#xff0c;但需要学习的内容有很多&#xff0c;其中包括Linux、数据库、渗透测试、等保…

ue5肉鸽游戏视频教程学习记录

先在虚幻商城下载免费的paperzd插件&#xff0c;并启用。 导入资源后&#xff0c;先通过应用paper2d纹理资源&#xff0c;将去掉导入ue时产生的边缘模糊&#xff0c;再点击下面的创建瓦片集&#xff0c; 打开瓦片集&#xff0c;发现选中不对&#xff0c; 改变瓦片大小为16*…