【Redis系列】Java操作Redis客户端

【Redis系列】Java操作Redis客户端


🚀 欢迎来到我的ZEEKLOG博客:Optimistic _ chen
一名热爱技术与分享的全栈开发者,在这里记录成长,专注分享编程技术与实战经验,助力你的技术成长之路,与你共同进步!


🚀我的专栏推荐

专栏内容特色适合人群
🔥C语言从入门到精通系统讲解基础语法、指针、内存管理、项目实战零基础新手、考研党、复习
🔥Java基础语法系统解释了基础语法、类与对象、继承Java初学者
🔥Java核心技术面向对象、集合框架、多线程、网络编程、新特性解析有一定语法基础的开发者
🔥Java EE 进阶实战Servlet、JSP、SpringBoot、MyBatis、项目案例拆解想快速入门Java Web开发的同学
🔥Java数据结构与算法图解数据结构、LeetCode刷题解析、大厂面试算法题面试备战、算法爱好者、计算机专业学生
🔥Redis系列从数据类型到核心特性解析项目必备

🚀我的承诺:
✅ 文章配套代码:每篇技术文章都提供完整的可运行代码示例

✅ 持续更新:专栏内容定期更新,紧跟技术趋势

✅ 答疑交流:欢迎在文章评论区留言讨论,我会及时回复(支持互粉)


🚀 关注我,解锁更多技术干货!
⏳ 每天进步一点点,未来惊艳所有人!✍️ 持续更新中,记得⭐
收藏关注⭐不迷路 ✨

📌 标签:#技术博客#编程学习#Java#C语言#算法#程序员

文章目录

前言

【Redis系列】常用数据结构—String
【Redis系列】常用数据结构—Hash类型
【Redis系列】常用数据结构—List类型
【Redis系列】常用数据结构—SET类型
【Redis系列】常用数据结构—ZSET类型
前面的学习主要是各种redis的基本操作/命令,都是在redis命令行客户端手动执行的,这种方式对于日常开发来说很难上手使用,所以更多时候,程序员们都使用redis的api,使用定制化的redis客户端程序,进一步操作redis服务器(这种操作类似使用MyBatis操作数据库),用程序来操作redis服务器。

Jedis

因为redis官方公布了redis服务器使用的协议:RESP。所以任何人都可以通过这个协议来实现一个和redis服务器通信的客户端程序。我们可以将各大佬做好的客户端库直接调用(反正我实现不了)。Java体系中封装了RESP协议,有很多大佬实现了redis客户端的库,今天我们使用jedis库,通过maven引入。


现在我们的redis客户端就在我们的idea上,而redis服务器却在我的云服务器上,两者之间的通信必须经过外网IP来访问到我的服务器,才能到达redis服务器。

在这里插入图片描述

这种情况,

  1. 要么我把程序打一个jar包,把jar包拷贝到Linux服务器上去执行

要么配置ssh端口转发,把云服务器的redis通信端口,映射到本地主机。

在这里插入图片描述

很明显,选择第二种方法会更加方便,否则redis每次进行通信都要对程序进行打包。

ssh端口转发


那么问题来了,SSH是怎么进行端口转发的?


SSH(Secure Shell) 是一种网络协议,用于在不安全的网络(如互联网)上提供安全的远程登录和安全的网络服务。
我们的XShell中就有这种协议,XShell远程登录到云服务器,通过SSH协议完成本地端口转发,将远程服务的端口映射到本地。

在这里插入图片描述


ssh默认走22端口,整个过程就是在本地构造一个ssh数据报,把对redis的通信放到ssh数据报中,整个数据报通过ssh的22端口发送给云服务器,云服务器解析数据报,然后把数据交给redis6379端口,完成整个通信过程。

后续Java代码中,通过127.0.0.1:8888就能操作到云服务器中的redis了。

注意:除了配置ssh端口映射之外,还要修改redis服务器的配置,修改绑定的ip( 默认只能本机访问,不能跨主机访问);以及关闭保护模式(默认是yes,不能跨主机访问)

连接redis服务器

创建maven项目,引入jedis的依赖到pom.xml中

<!-- https://mvnrepository.com/artifact/redis.clients/jedis --> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>4.3.2</version> </dependency> 
  • 使⽤JedisPool描述Redis服务器的位置.使⽤url来表⽰
  • 使用getResource和服务器建立连接
//连接到redis服务器上 JedisPool jedisPool=new JedisPool("tcp://127.0.0.1:8888");try(Jedis jedis=jedisPool.getResource()){ String pong=jedis.ping(); System.out.println(pong);}
  • 连接使用完后要close关闭,也可以使用try自动关闭

通过ping检测连接是否建立

在这里插入图片描述


getResource() 就像去图书馆借书,不是买新书(创建连接),而是从书库(jedisPool连接池)里借一本已有的书,用完要还(close()),这样别人才能继续借。

Java操作命令

在程序中调用方法,其实和我们在命令行客户端中是一样的,只是把命令变为被调用的方法。因为之前我们系统写过基本的命令, 这里只简单展示一下即可。

通用命令

set和get

publicstaticvoidtest1(Jedis jedis){System.out.println("get和set的使用");//先情况数据库,避免上一组数据影响下一组测试 jedis.flushAll(); jedis.set("key1","111"); jedis.set("key2","222");String value1=jedis.get("key1");System.out.println("value"+value1);String value2=jedis.get("key2");System.out.println("value"+value2);}publicstaticvoidmain(String[] args){//连接到redis服务器上JedisPool jedisPool=newJedisPool("tcp://127.0.0.1:8888");try(Jedis jedis=jedisPool.getResource()){String pong=jedis.ping();System.out.println(pong);test1(jedis);test2(jedis);}}
在这里插入图片描述

exists和del

  • exists 命令来检查给定的键是否存在。该命令会返回一个整数,表示键是否存在:1 表示存在,0 表示不存在
  • del可以删除多个key,以变长参数列表的方式体现,返回值是实际删除的key的个数
private static void test2(Jedis jedis){ jedis.set("key1","111"); jedis.set("key2","222"); jedis.set("key3","333");//检测key1是否存在 boolean ret=jedis.exists("key1"); System.out.println(ret);//删除key1 long n=jedis.del("key1"); System.out.println(n);//检测key1是否存在 ret=jedis.exists("key1"); System.out.println(ret);//批量删除 n=jedis.del("key3","key2"); System.out.println(n);}
在这里插入图片描述

string类型命令

append

append:字符串追加

private static void test3(Jedis jedis){ jedis.append("key2","hello "); String value=jedis.get("key2"); System.out.println(value); jedis.append("key2","redis String"); value=jedis.get("key2"); System.out.println(value);}
在这里插入图片描述

incrby 和 decrby

  • incrby对key的数值增加指定数量。如果不存在该键,则在执行递增前将其初始化为0。该命令是原子命令,仅对数值有效。
  • decrby对密钥的数值减少指定数量。如果不存在该键,则在执行递减前将其初始化为0。该命令是原子命令,仅对数值有效。
private static void test4(Jedis jedis){ jedis.set("key","0"); jedis.incrBy("key",5);//+5 System.out.println(jedis.get("key")); jedis.decrBy("key",3);//-3 System.out.println(jedis.get("key"));}
在这里插入图片描述

list类型命令

lrange

  • lrange获取指定区间元素
private static void test5(Jedis jedis){ jedis.rpush("list","1","2","3","4"); List<String> values=jedis.lrange("list",1,3); System.out.println(values);}
在这里插入图片描述

linsert

  • 通过 ListPosition.BEFORE ListPosition.AFTER 标识插⼊位置.
private static void test6(Jedis jedis){ jedis.rpush("list2","a","b","c","e"); jedis.linsert("list2", ListPosition.BEFORE,"e","d"); List<String> values=jedis.lrange("list2",0,-1); System.out.println(values);}
在这里插入图片描述

Hash类型

hkeys 和 hvals

  • hkeys返回哈希表中所有键的列表。返回列表中字段的顺序无法保证
  • hvals返回哈希表中所有值的列表。返回列表中值的顺序与 HKEYS 返回的字段顺序相对应
private static void test7(Jedis jedis){ jedis.hset("hash1","name","zhangsan"); jedis.hset("hash1","age","20");Set<String> keys=jedis.hkeys("hash1"); System.out.println(keys); List<String> values=jedis.hvals("hash1"); System.out.println(values);}
在这里插入图片描述

set命令

srem 和 sismember

  • srem:删除集合中的指定元素,如果删除成功返回1,如果不存在则什么都不做返回0;如果指定的键不是集合类型则会报错。
  • sismember:查看一个元素是否在集合中,如果在集合中返回1,如果不在集合中,或者指定集合的键不存在则返回0;如果指定的键存在但是不是集合类型则会报错。
private static void test8(Jedis jedis){ jedis.sadd("set1","aaa","bbb","ccc"); boolean ret=jedis.sismember("set1","bbb"); System.out.println(ret); long n= jedis.srem("set1","aaa","bbb"); System.out.println(n); ret=jedis.sismember("set1","aaa"); System.out.println(ret); ret=jedis.sismember("key1","111"); System.out.println(ret);}
在这里插入图片描述


在这里插入图片描述

sdiff

  • sdiff求差集,返回结果列表
private static void test9(Jedis jedis){ jedis.sadd("set2","aaa","bbb","ccc","ddd"); jedis.sadd("set3","aaa","eee","ccc","fff");Set<String> ret=jedis.sdiff("set2","set3"); System.out.println(ret);}
在这里插入图片描述

ZSet类型

zcard 和 zscore

  • zcard返回 key 的成员个数。 key不存在时,返回0
  • zscore返回指定 key 和 member 的 分数值
private static void test10(Jedis jedis){ jedis.zadd("zset",100,"张三"); jedis.zadd("zset",99,"李四"); jedis.zadd("zset",94,"赵六"); jedis.zadd("zset",96,"王五"); jedis.zadd("zset",80,"小王"); jedis.zadd("zset",85,"小赵"); long n=jedis.zcard("zset"); System.out.println(n); double score=jedis.zscore("zset","小王"); System.out.println(score);}
在这里插入图片描述

zinterstore

  • zinterstore计算多个有序集合的交集,并将结果存储在新的有序集合中
private static void test11(Jedis jedis){ jedis.zadd("zset1",100,"张三"); jedis.zadd("zset1",99,"李四"); jedis.zadd("zset1",85,"小赵"); jedis.zadd("zset2",100,"张三"); jedis.zadd("zset2",99,"李四"); jedis.zadd("zset2",94,"赵六"); jedis.zadd("zset2",96,"王五"); jedis.zadd("zset2",80,"小王"); jedis.zadd("zset2",85,"小赵"); long n=jedis.zinterstore("zset3","zset1","zset2"); System.out.println(n);//Tuple元组是一种数据结构,可以容纳固定数量的元素,每个元素可能类型不同 List<Tuple> tuples=jedis.zrangeWithScores("zset3",0,-1); System.out.println(tuples);}
在这里插入图片描述

完结撒花!🎉

如果这篇博客对你有帮助,不妨点个赞支持一下吧!👍
你的鼓励是我创作的最大动力~

想获取更多干货? 欢迎关注我的专栏 → optimistic_chen
📌 收藏本文,下次需要时不迷路!

我们下期再见!💫 持续更新中……


悄悄说:点击主页有更多精彩内容哦~ 😊

在这里插入图片描述

Read more

【算法竞赛】C/C++ 的输入输出你真的玩会了吗?

【算法竞赛】C/C++ 的输入输出你真的玩会了吗?

🔭 个人主页:散峰而望 《C语言:从基础到进阶》《编程工具的下载和使用》《C语言刷题》《算法竞赛从入门到获奖》《人工智能AI学习》《AI Agent》 愿为出海月,不做归山云 🎬博主简介 文章目录 * 前言 * 1. OJ(online judge)题目输入情况汇总 * 1.1 单组测试用例 * 1.2 多组测试用例 * 1.2.1 测试数据组数已知 * 1.2.2 测试数据组未知 * 1.2.3 特殊值结束测试数据 * 2. 输入时特殊技巧 * 2.1 含空格字符串的特殊处理方式 * 2.2 数字的特殊处理方式 * 3. scanf/printf 和

By Ne0inhk
【C++ 类与对象 (下)】:进阶特性与编译器优化的深度实战

【C++ 类与对象 (下)】:进阶特性与编译器优化的深度实战

🎬 博主名称:月夜的风吹雨 🔥 个人专栏: 《C语言》《基础数据结构》《C++入门到进阶》 ⛺️任何一个伟大的思想,都有一个微不足道的开始! 💬 前言: 掌握了类的基础封装与默认成员函数后,很多开发者会在 “进阶特性” 上栽跟头: 为什么引用、const 成员必须用初始化列表?static 成员为什么不能在类内初始化?友元如何突破封装又不破坏设计?编译器为什么能把 “构造 + 拷贝” 优化成一步? 这些问题的答案,藏在 C++ 类与对象的进阶设计里。本篇文章将从 “实战痛点” 出发,结合底层逻辑与代码示例,带你理解这些特性的 “设计初衷” 与 “正确用法”,避开工程开发中的高频陷阱。 ✨ 阅读后,你将掌握:初始化列表的底层逻辑与强制使用场景静态成员的共享机制与实战案例(如对象计数)友元与内部类的封装权衡技巧匿名对象的生命周期与使用场景编译器对对象拷贝的优化规则与验证方法 文章目录 * 一、再探构造函数:初始化列表的底层逻辑 * 1. 初始化列表的基础语法 * 2. 必须用初始化列表的

By Ne0inhk

C++ 中 UTF-8 编码字符的使用指南:从基础到非 UTF-8 文件适配

C++ 中 UTF-8 编码字符的使用指南:从基础到非 UTF-8 文件适配 在全球化软件开发中,UTF-8 作为通用字符编码标准,是 C++ 处理多语言(尤其是中文)的核心选择。但 UTF-8 在 C++ 中的正确使用需兼顾源文件编码、编译器配置、字符串处理等多重因素,非 UTF-8 源文件场景更易出现编码混乱。本文结合实践细节,系统梳理 UTF-8 字符的使用方法与适配技巧。 一、C++ 中 UTF-8 字符的基础使用 UTF-8 在 C++ 中的落地需建立在 “源文件 - 编译器 - 运行环境” 的编码一致性基础上,核心步骤包括源文件配置、字符串定义、编译器适配三大环节。 1. 源文件编码:UTF-8

By Ne0inhk
SkyWalking - .NET / C++ / Lua 探针现状与社区支持

SkyWalking - .NET / C++ / Lua 探针现状与社区支持

👋 大家好,欢迎来到我的技术博客! 📚 在这里,我会分享学习笔记、实战经验与技术思考,力求用简单的方式讲清楚复杂的问题。 🎯 本文将围绕SkyWalking这个话题展开,希望能为你带来一些启发或实用的参考。 🌱 无论你是刚入门的新手,还是正在进阶的开发者,希望你都能有所收获! 文章目录 * SkyWalking - .NET / C++ / Lua 探针现状与社区支持 🌐 * 一、SkyWalking 多语言探针架构概览 🧩 * 二、Java 探针:成熟稳定,功能最全 ☕️ * 示例:Spring Boot 应用接入 SkyWalking * Java 探针高级特性 * 三、.NET 探针现状:渐趋成熟,生产可用 🖥️ * 技术原理 * 使用方式 * 当前支持的功能 * 局限性 * 四、C++ 探针现状:SDK 形式,适合嵌入式场景 ⚙️ * cpp2sky SDK

By Ne0inhk