【Redis】Java操作Redis(Jedis客户端使用)

Redis不仅支持简单的键值存储,还提供了丰富的数据结构(如列表、哈希表、集合等)和强大的原子操作,使得它在存储和处理数据时非常高效。关于这些数据结构的学习可以学习下面的博客:

【Redis】String的常用命令及图解String使用场景_string命令在做什么-CSDN博客

【Redis】哈希类型的常用命令以及使用场景-CSDN博客

【Redis】List的常用命令以及常用场景-CSDN博客

【Redis】Set 集合常用命令以及使用场景-CSDN博客

【Redis】Zset有序集合常用命令以及使用场景-CSDN博客

1. 引言

在实际的开发中,我们总不可能直接还是在redis-cli中使用命令来操作吧。就像是MySQL我们可以通过JDBC\MyBatis等来操作数据库,在java中同样可以使用java客户端的Jedis来操作redis。使用Redis客户端,比如Jedis,可以方便地在Java应用程序中与Redis进行通信,从而利用其快速的数据读写能力和丰富的数据操作功能。

Jedis是Redis官方推荐的Java客户端之一,它基于Redis的RESP(Redis Serialization Protocol)协议实现,提供了简洁清晰的API,支持连接池管理和管道操作,同时在社区中有广泛的使用和支持。

在使用Jedis作为Java应用与Redis交互的客户端时,一个常见的问题是其线程安全性Jedis是直连模式的客户端,意味着在多线程环境下共享一个Jedis实例可能会导致数据混乱和不一致性。

edis的线程不安全性主要源于其底层的RedisOutputStream和RedisInputStream对象,它们是Jedis中的全局属性。当多个线程同时使用同一个Jedis实例时,它们会共享这些全局属性,这可能导致以下问题:

  1. 数据混乱和不一致性: 多个线程同时操作Redis的写流和读流,可能导致数据的交叉写入或读取,从而产生不可预测的结果。
  2. 并发操作异常: 在高并发情况下,多个线程对同一个Jedis实例的并发操作可能触发Jedis内部状态的不一致,进而导致异常或数据丢失。

解决方案:使用Jedis连接池(JedisPool)

为了避免上述问题,推荐的做法是为每个线程分配独立的Jedis实例,而不是共享一个实例。这可以通过Jedis连接池(JedisPool)来实现,连接池能够有效地管理多个Jedis实例,并确保线程安全的使用方式。

2. 快速上手

2.1 配置相关以及环境要求

在maven仓库找到Jedis的依赖:

<dependencies><!-- https://mvnrepository.com/artifact/redis.clients/jedis --><dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>4.4.2</version></dependency></dependencies>

在导入依赖后,并不是直接写代码就可以上手的。目前一般来说使用的环境是在windows上,而现在我的Redis客户端是在服务器上的。直接开放redis的端口是比较危险的,因此这里一般有两个做法:

  1. 直接让java程序也在服务器上运行。也就是把自己写好的代码打成jar包拷贝到linux的服务器上执行。手动还挺麻烦的,也有一些第三方的插件来简化这些步骤;
  2. 配置ssh端口转发,把云服务器的redis端口映射到本地主机。

这里主要讲解一下通过配置端口转发来解决上述问题。

此时访问本地端口就相当于访问远程服务器的端口。

在 xshell 中,进行如下配置:
1)右键云服务器的会话,选择属性

2)找到隧道 ->配置转移规则

3) 使⽤该会话连接服务器.
此时,访问本地的 8888,就相当于访问对应服务器的 6379。注意,xshell和服务器必须处在连接状态,这样的映射才是有效的。
此外,还要注意安装redis的配置文件设置,可以去看博客: Redis介绍及安装配置_credis安装-CSDN博客的第三节。

 2.2 连接Redis Server

public class RedisExample {public static void main(String[] args) {// 创建Jedis对象,指定Redis服务器地址和端口号Jedis jedis = new Jedis("127.0.0.1", 8888);// 如果Redis服务器设置了密码,需要进行认证// jedis.auth("password");// 测试连接是否正常System.out.println("连接成功");// 存储数据jedis.set("name", "Alice");String value = jedis.get("name");System.out.println("Stored value in Redis: " + value);// 关闭连接jedis.close();}

3.3 Jedis针对不同数据结构

Redis支持多种数据结构,例如哈希表、列表、集合等,可以使用Jedis进行操作:

/ 连接Redis
Jedis jedis = new Jedis("localhost", 6379);// 使用哈希表存储用户信息
jedis.hset("user:1", "name", "Alice");
jedis.hset("user:1", "age", "30");// 获取用户信息
String name = jedis.hget("user:1", "name");
String age = jedis.hget("user:1", "age");
System.out.println("User name: " + name + ", age: " + age);// 关闭连接
jedis.close();

jedis实例实现了大多数Redis命令。有关支持的命令的完整列表,请参阅jedis Javadocs:Jedis - jedis 5.2.0-beta4 javadocicon-default.png?t=N7T8https://www.javadoc.io/doc/redis.clients/jedis/latest/redis/clients/jedis/Jedis.html 

3.4 连接池管理

在Java应用中使用Jedis操作Redis时,使用连接池(如JedisPool)是非常重要的。

Jedis实例是线程不安全的。Jedis实例中的RedisOutputStreamRedisInputStream是全局属性,当多个线程同时使用同一个Jedis实例时,会导致数据混乱和不可预测的结果。因此,需要保证每个线程都使用独立的Jedis实例。

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;public class RedisExample {private static JedisPool jedisPool;static {// 配置连接池JedisPoolConfig poolConfig = new JedisPoolConfig();poolConfig.setMaxTotal(10); // 设置最大连接数poolConfig.setMaxIdle(5);   // 设置最大空闲连接数poolConfig.setMinIdle(1);   // 设置最小空闲连接数poolConfig.setTestOnBorrow(true); // 借用连接时进行测试// 初始化连接池jedisPool = new JedisPool(poolConfig, "localhost", 8888, 2000, "your_redis_password"); // 如果有密码,请填写}public static void main(String[] args) {// 使用连接池获取Jedis实例try (Jedis jedis = jedisPool.getResource()) {// 测试连接是否正常System.out.println("连接成功: " + jedis.ping());// 进行Redis操作jedis.set("key", "value");String value = jedis.get("key");System.out.println("Stored value in Redis: " + value);} catch (Exception e) {e.printStackTrace();} finally {// 关闭连接池if (jedisPool != null) {jedisPool.close();}}}
}

连接池配置解释

  • setMaxTotal: 最大连接数,连接池中能够分配的最大Jedis实例数。
  • setMaxIdle: 最大空闲连接数,连接池中允许保留的最大空闲Jedis实例数。
  • setMinIdle: 最小空闲连接数,连接池中最小的空闲Jedis实例数,低于这个数量时,连接池会创建新的实例。
  • setTestOnBorrow: 借用连接时进行测试,确保获取的Jedis实例可用。

对于线程池还不了解到可以去看这篇博客:

深入解剖线程池(ThreadPoolExecutor)_newfixedthreadpool 线程释放-CSDN博客
线程池中的参数很相似。

连接池参数源码

public class RedisPoolUtils {private static JedisPool jedisPool = null;/*** redis服务器地址*/private static String addr = "127.0.0.1";/*** redis服务器端口*/private static int port = 6379;/*** redis服务器密码*/private static String auth = "111111";static {try {JedisPoolConfig config = new JedisPoolConfig();// 连接耗尽时是否阻塞, false报异常,ture阻塞直到超时, 默认trueconfig.setBlockWhenExhausted(true);// 设置的逐出策略类名, 默认DefaultEvictionPolicy(当连接超过最大空闲时间,或连接数超过最大空闲连接数)config.setEvictionPolicyClassName("org.apache.commons.pool2.impl.DefaultEvictionPolicy");// 是否启用pool的jmx管理功能, 默认trueconfig.setJmxEnabled(true);// MBean ObjectName = new ObjectName("org.apache.commons.pool2:type=GenericObjectPool,name=" + "pool" + i); 默认为"pool", JMX不熟,具体不知道是干啥的...默认就好.config.setJmxNamePrefix("pool");// 是否启用后进先出, 默认trueconfig.setLifo(true);// 最大空闲连接数, 默认8个config.setMaxIdle(8);// 最大连接数, 默认8个config.setMaxTotal(8);// 获取连接时的最大等待毫秒数(如果设置为阻塞时BlockWhenExhausted),如果超时就抛异常, 小于零:阻塞不确定的时间,  默认-1config.setMaxWaitMillis(-1);// 逐出连接的最小空闲时间 默认1800000毫秒(30分钟)config.setMinEvictableIdleTimeMillis(1800000);// 最小空闲连接数, 默认0config.setMinIdle(0);// 每次逐出检查时 逐出的最大数目 如果为负数就是 : 1/abs(n), 默认3config.setNumTestsPerEvictionRun(3);// 对象空闲多久后逐出, 当空闲时间>该值 且 空闲连接>最大空闲数 时直接逐出,不再根据MinEvictableIdleTimeMillis判断  (默认逐出策略)config.setSoftMinEvictableIdleTimeMillis(1800000);// 在获取连接的时候检查有效性, 默认falseconfig.setTestOnBorrow(false);// 在空闲时检查有效性, 默认falseconfig.setTestWhileIdle(false);// 逐出扫描的时间间隔(毫秒) 如果为负数,则不运行逐出线程, 默认-1config.setTimeBetweenEvictionRunsMillis(-1);jedisPool = new JedisPool(config, addr, port, 3000, auth);} catch (Exception e) {e.printStackTrace();}}/*** 获取 Jedis 资源** @return*/public static Jedis getJedis() {if (jedisPool != null) {return jedisPool.getResource();}return null;}/*** 释放Jedis资源*/public static void close(final Jedis jedis) {if (jedis != null) {jedis.close();}}
}

 

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

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

相关文章

OBD诊断(ISO15031) 01服务

文章目录 功能简介PID 的功能请求和响应1、read-supported PIDs1.1、请求1.2、肯定响应 2、read PID value1.1、请求1.2、肯定响应 3、同时请求多个PID3、同时读取多个PID数据 Parameter definition报文示例1、单个PID请求和读取2、多个PID请求和读取 功能简介 01服务&#xf…

XML 技术

XML 技术 XML(可扩展标记语言)是一种用于存储和传输数据的标记语言。它由万维网联盟(W3C)开发,并在1998年成为正式标准。XML的设计目标是既易于人类阅读,也易于机器解析。它是一种自描述的语言,允许用户定义自己的标签和文档结构。XML被广泛应用于各种领域,包括网络服…

【Ubuntu24.04无显示器远控】【Todesk远程桌面黑屏】【Linux虚拟显示器】解决方案

1️⃣版本 Ubuntu 24.04Todesk 4.7.2.0xserver-xorg-video-dummy 1:0.4.0-1build1 2️⃣安装配置虚拟显示器 sudo apt install xserver-xorg-video-dummy编辑/etc/gdm3/custom.conf&#xff0c;关闭Ubuntu24.04Wayland切换为X11 WaylandEnablefalse /usr/share/X11/xorg.con…

NDT(基于正态分布变换的配准算法)

NDT是将单个扫描的离散点集转换为空间上定义的分段连续可微概率密度&#xff0c;该概率密度由一组易于计算的正态分布组成的算法。采用NDT连续化后&#xff0c;传统硬离散优化问题能够潜在地转化为更易于处理的连续优化问题。 NDT原理 NDT将根据点云中点所处的位置&#xff0…

网络治理新模式:Web3时代的社会价值重构

随着Web3技术的崛起&#xff0c;传统的网络治理模式正在经历革新&#xff0c;这不仅仅是技术的进步&#xff0c;更是对社会价值观念的挑战和重构。本文将深入探讨Web3时代的网络治理新模式&#xff0c;其背后的技术基础、社会影响以及未来的发展方向。 1. 引言 Web3时代&#…

Java中的函数式编程入门

Java中的函数式编程入门 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;今天我来为大家介绍一下Java中的函数式编程。随着Java 8的发布&#xff0c;函数式编程成…

使用Spring Boot实现与ActiveMQ的消息队列集成

使用Spring Boot实现与ActiveMQ的消息队列集成 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01; 消息队列在现代分布式系统中扮演着至关重要的角色&#xff0c;…

智慧营区人员管理系统|DW-S406系统特点

1、项目背景 当前我国军队正处于加紧完成机械化和信息化建设双重历史任务的阶段&#xff0c;现阶段我国对军事通信领域强有力的支持性产业政策&#xff0c;将为行业的未来发展提供有力保障。随着经济实力的不断增长&#xff0c;以及国际、周边政治局势的日趋复杂&#xff0c;我…

# 音频处理4_傅里叶变换

1.离散傅里叶变换 对于离散时域信号 x[n]使用离散傅里叶变换&#xff08;Discrete Fourier Transform, DFT&#xff09;进行频域分析。 DFT 将离散信号 x[n] 变换为其频谱表示 X[k]&#xff0c;定义如下&#xff1a; X [ k ] ∑ n 0 N − 1 x [ n ] e − j 2 π k n N X[k]…

详细学习es6扩展运算符

ES6中的扩展运算符&#xff08;Spread Operator&#xff09;是一种非常方便的语法&#xff0c;主要用于将可迭代对象&#xff08;比如数组、字符串等&#xff09;展开成多个参数。以下是关于ES6扩展运算符的详细内容&#xff1a; 用法&#xff1a; 在数组字面量中展开数组&am…

C# 超简单的离线人脸识别库 - ViewFaceCore

项目介绍 ViewFaceCore是一个基于 SeetaFace6 的 .NET 人脸识别解决方案。 项目特点 开源&#xff08;MIT license&#xff09;、免费、简单的离线人脸识别库。 跨平台&#xff08;适用于 Windows、MacOS 和 Linux &#xff09;。 .NET 框架 和 操作系统 封装完善的NuGet包…

《昇思25天学习打卡营第1天 | 快速入门 mindspore》

1. 背景&#xff1a; 今天开始参与 CSDN 的活动&#xff0c;使用 mindspore 学习神经网络&#xff0c;先学习的是第二小节&#xff1b; 2. 训练的内容&#xff1a; 第二小节内容&#xff1a; 使用 mindspore &#xff0c;构建 DenseNet&#xff0c;识别手写字符&#xff1b;…

[CAN] 通讯协议手动解析与手动打包 [手撕编码格式]

手动解析与手动打包 一、Intel格式编码1.1 报文解析。1.2 报文打包二、Motorola格式通讯协议2.1 报文解析。2.2 报文打包🙋 前言 CAN有两种编码格式:Intel编码格式 和 Motorola编码格式,本教程将分别对两种格式进行手动解析与手动打包。 一、Intel格式编码 假设已知雷达CAN…

医疗数据分析

我待过2家大公司做医疗的&#xff0c;发现了他们的共性&#xff0c;有很多通用的方法&#xff0c;先说数据&#xff0c;医疗数据中最麻烦的&#xff0c;我觉得就是检验数据。 为什么&#xff1f;因为检查的指标项多&#xff0c;占所有数据的百分之50以上。 指标歧义: 血红蛋…

接口自动化测试框架实战(Pytest+Allure+Excel)

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 1. Allure 简介 Allure 框架是一个灵活的、轻量级的、支持多语言的测试报告工具&#xff0c;它不…

凡人修仙传单机版的激活码

谁有凡人修仙传单机版的激活码&#xff0c;急 首页 用户 合伙人 商城 法律 手机答题 我的 谁有凡人修仙传单机版的激活码&#xff0c;急 能玩就行&#xff0c;有的请留下QQ号码&#xff0c;我们私聊&#xff0c;感激不尽。 分享 举报 2个回答#热议# 不吃早饭真的会得胆结石吗&a…

项目开发 TCP-Socket连接功能实现(Android端)

前段时间在公司做项目的时候遇到了一个功能需要使用TCP-Socket连接硬件设备进行通信&#xff0c;查了很多资料也只是关于HTTP-Socket相关的&#xff0c;没法满足项目的要求&#xff0c;后来查到一个相关的插件&#xff0c;现在有时间和大家分享一下。 项目简单介绍&#xff1a…

如何在Windows 11中修复Wi-Fi的常见问题?这里有详细步骤

序言 如今,每个人都需要互联网,所以Wi-Fi瘫痪可能会引起恐慌。然而,永远不要害怕,因为有很多久经考验的方法可以让Wi-Fi重新上线!Windows 11中Wi-Fi最常见的问题也有常见的解决方案。 当你的Windows 11 Wi-Fi不工作时该怎么办 如果你注意到你的电脑没有连接到互联网,这…

关于Vue组件间通信会问到哪些面试题?

在Vue面试中&#xff0c;关于组件间通信的问题是非常常见的。以下是一些可能会问到的面试题&#xff1a; Vue组件间通信的基本方式有哪些&#xff1f; 父向子传&#xff1a; 子组件通过props接收父组件传递的数据。子组件可以直接通过this.$parent.xxx使用父组件的数据&#x…

使用MoA(Mixture of Agents)混合智能体技术,结合多个开源大语言模型如Llama3、phi-3和Mistral,实现一个强大的AI智能体

1.简介 论文简介: 论文提出了一种称为混合智能体(Mixture-of-Agents,MoA)的方法,利用多个大语言模型(LLM)的集体智慧来提高自然语言理解和生成任务的性能。 MoA采用了分层结构,每一层包含多个LLM智能体。每个智能体都将前一层所有智能体的输出作为辅助信息来生成自己的回答。通…