Java项目中集成Redis提升系统的性能

news/2024/5/18 14:33:33/文章来源:https://blog.csdn.net/icoolno1/article/details/128107389

概述

安装Redis

安装

启动Rocky Linux 9.0,在浏览器中打开web console.

如果没有安装Web console,按以下步骤安装启用:
安装命令:
# dnf install cockpit
启用并运行服务
# systemctl enable --now cockpit.socket
开通防火墙:
# firewall-cmd --add-service=cockpit --permanent
# firewall-cmd --reload
rocky的软件仓库里自带了redis,直接yum安装就可以了。点击Web console左边菜单中的终端或Terminal,进入控制台模式。
控制台
然后敲入命令:
# dnf install redis -y
安装完成后,启用服务:
# systemctl enable --now redis
测试安装结果:
# redis-cli ping
如果返回PONG,说明安装成功。

配置

允许外部访问

用vi打开配置文件:
# vi /etc/redis/redis.conf
修改ip4绑定地址为任意,即0.0.0.0
监听地址
按Esc,输入:wq退出。重启Redis:
# systemctl restart redis
添加防火墙:
# firewall-cmd --add-port 6379/tcp --permanent
# firewall-cmd --reload
验证一下安装,找另外一台机器,打开命令行输入:
telnet 192.168.0.128 6379
如果屏幕被清空,说明连接成功,输入quit退出。

写个程序测试一下是否配置成功。

SpringBoot里的spring-boot-starter-data-redis里使用的是lettuce客户端,所以我们这里也用这个。

<dependency><groupId>io.lettuce</groupId><artifactId>lettuce-core</artifactId><version>6.2.1.RELEASE</version>
</dependency>

写段测试代码:

package redis;import java.time.LocalDateTime;import io.lettuce.core.RedisClient;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.api.sync.RedisCommands;public class DemoMain {public static void main(String[] args) {RedisClient redisClient = RedisClient.create("redis://192.168.0.128:6379/0");StatefulRedisConnection<String, String> connection = redisClient.connect();RedisCommands<String, String> syncCommands = connection.sync();syncCommands.set("key", "Hello, Redis!"+LocalDateTime.now());connection.close();redisClient.shutdown();System.out.println("ok!");}}

进入服务器查下结果:

redis-cli get key
“Hello, Redis!2022-12-01T11:44:55.654705500”

限制访问

为了不让别的应用随便接入redis,我们可以修改redis.conf加上访问密码,找到这一行改成这样:
增加密码验证
保存后重启redis服务。此时运行上边的程序,发现报错,错误提示:

NOAUTH HELLO must be called with the client already authenticated,
otherwise the HELLO AUTH <user> <pass> option can be used to
authenticate the client and select the RESP protocol version at the
same time

大概意思就是没发起验证命令。然后我们修改一下,先加入错误的密码:

package redis;import java.time.LocalDateTime;import io.lettuce.core.RedisClient;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.api.sync.RedisCommands;public class DemoMain {public static void main(String[] args) {RedisClient redisClient = RedisClient.create("redis://111111@192.168.0.128:6379/0");StatefulRedisConnection<String, String> connection = redisClient.connect();RedisCommands<String, String> syncCommands = connection.sync();syncCommands.set("key", "Hello, Redis!"+LocalDateTime.now());connection.close();redisClient.shutdown();System.out.println("ok!");}}

运行程序后提示无效的用户名密码:

WRONGPASS invalid username-password pair or user is disabled.

换成正确的密码后,程序正常执行。

启用加密传输

  1. 生成证书
    生成密钥:

openssl genrsa -out server.key 4096

生成证书请求文件:
注意,证书需要配合域名使用。

openssl req -new -key server.key -out server.csr

生成CA证书:

openssl x509 -req -in server.csr -out server.crt -signkey server.key -days 3650

  1. 服务端配置
    端口:

port 0
tls-port 6379

关闭客户端证书验证

tls-auth-clients no

指定证书路径:

tls-cert-file /etc/redis/server.crt
tls-key-file /etc/redis/server.key
tls-ca-cert-file /etc/redis/server.crt

  1. 客户端导入证书

keytool -import -alias demo -file server.crt -keystore E:\openjdk\jdk-17\lib\security\cacerts -storepass changeit

  1. 修改代码
package redis;import java.io.File;
import java.net.URL;
import java.time.LocalDateTime;import io.lettuce.core.ClientOptions;
import io.lettuce.core.RedisClient;
import io.lettuce.core.RedisURI;
import io.lettuce.core.SslOptions;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.api.sync.RedisCommands;public class DemoMain {public static void main(String[] args) throws Throwable {RedisURI redisUri = RedisURI.Builder.redis("demo.com", 6379).withDatabase(0).withSsl(true).withPassword("123456").withVerifyPeer(false).build();RedisClient redisClient = RedisClient.create(redisUri);SslOptions sslOptions = SslOptions.builder().jdkSslProvider().protocols("TLSv1.2").truststore(new File("E:\\openjdk\\jdk-17\\lib\\security\\cacerts"), "changeit").build();ClientOptions clientOptions = ClientOptions.builder().sslOptions(sslOptions).build();redisClient.setOptions(clientOptions);StatefulRedisConnection<String, String> connection = redisClient.connect();RedisCommands<String, String> syncCommands = connection.sync();syncCommands.set("key", "Hello, Redis!" + LocalDateTime.now());connection.close();redisClient.shutdown();System.out.println("ok!");}}

项目实战

创建Springboot项目

先用IDE生成Maven项目,再往pom.xml里加入springboot的相关依赖。pom.xml内容如下:

<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>java-demo</groupId><artifactId>root</artifactId><version>0.0.1-SNAPSHOT</version></parent><artifactId>redis-practice</artifactId><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target><lombok.version>1.18.24</lombok.version><spring-boot.version>2.7.4</spring-boot.version></properties><dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>${spring-boot.version}</version><type>pom</type><scope>import</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>${lombok.version}</version><scope>provided</scope></dependency></dependencies></dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope><optional>true</optional></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><exclusions><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-tomcat</artifactId></exclusion></exclusions></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-undertow</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jdbc</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>org.postgresql</groupId><artifactId>postgresql</artifactId><scope>runtime</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><version>${spring-boot.version}</version><configuration><executable>true</executable></configuration><executions><execution><goals><goal>repackage</goal></goals></execution></executions></plugin></plugins></build>
</project>

配置redis

为了使用密码验证及启用加密传输,我们要自定义 Lettuce的配置类:

package demo;import java.io.File;
import java.time.Duration;
import java.util.Optional;import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;import io.lettuce.core.ClientOptions;
import io.lettuce.core.ReadFrom;
import io.lettuce.core.SslOptions;
import io.lettuce.core.resource.ClientResources;public class LettuceSslClientConfiguration implements LettuceClientConfiguration {@Overridepublic boolean isUseSsl() {// TODO Auto-generated method stubreturn true;}@Overridepublic boolean isVerifyPeer() {// TODO Auto-generated method stubreturn false;}@Overridepublic boolean isStartTls() {// TODO Auto-generated method stubreturn false;}@Overridepublic Optional<ClientResources> getClientResources() {// TODO Auto-generated method stubreturn Optional.empty();}@Overridepublic Optional<ClientOptions> getClientOptions() {SslOptions sslOptions = SslOptions.builder().jdkSslProvider().protocols("TLSv1.2").truststore(new File("E:\\openjdk\\jdk-17\\lib\\security\\cacerts"), "changeit").build();ClientOptions clientOptions = ClientOptions.builder().sslOptions(sslOptions).build();return Optional.of(clientOptions);}@Overridepublic Optional<String> getClientName() {// TODO Auto-generated method stubreturn Optional.empty();}@Overridepublic Optional<ReadFrom> getReadFrom() {// TODO Auto-generated method stubreturn Optional.empty();}@Overridepublic Duration getCommandTimeout() {// TODO Auto-generated method stubreturn Duration.ZERO;}@Overridepublic Duration getShutdownTimeout() {// TODO Auto-generated method stubreturn Duration.ZERO;}@Overridepublic Duration getShutdownQuietPeriod() {// TODO Auto-generated method stubreturn Duration.ZERO;}}

然后配置实例Lettuce客户端实例:

package demo;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.StringRedisTemplate;@Configuration
class AppConfig {@Beanpublic LettuceConnectionFactory redisConnectionFactory() {var conf = new RedisStandaloneConfiguration("demo.com", 6379);conf.setDatabase(0);conf.setPassword("123456");return new LettuceConnectionFactory(conf, new LettuceSslClientConfiguration());}@BeanStringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {StringRedisTemplate template = new StringRedisTemplate();template.setConnectionFactory(redisConnectionFactory);return template;}
}

编写测试代码:

package demo;import java.io.IOException;
import java.util.UUID;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import com.fasterxml.jackson.databind.ObjectMapper;@RestController
@RequestMapping("/api/stat")
public class StatisticsController {@Autowiredprivate JdbcTemplate jdbcTemplate;@Autowiredprivate StringRedisTemplate redisTemplate;@GetMapping("{productId}")public ProductStat salesStat(@PathVariable UUID productId) throws IOException {ProductStat result = new ProductStat();var jsonStr = redisTemplate.opsForValue().get("product:" + productId);ObjectMapper mapper = new ObjectMapper();//从缓存中获取统计数据,如果没则云数据库中查询。if (jsonStr != null) {result = mapper.createParser(jsonStr).readValueAs(ProductStat.class);} else {int rowCount = this.jdbcTemplate.queryForObject("select count(*) from sale_order_item where product_id=?",Integer.class, productId);result.setSaleCount(rowCount);rowCount = this.jdbcTemplate.queryForObject("select count(*) from product_comment where product_id=?",Integer.class, productId);result.setCommentCount(rowCount);redisTemplate.opsForValue().set("product:" + productId, mapper.writeValueAsString(result));}return result;}
}

Postman验证

在这里插入图片描述

总结

Redis本身概念不是很难,就是将一些数据放在内存中,这样可以避开一些耗时的磁盘IO操作,以提升应用程序的性能。其难点在于安装配置,以及框架集成。如果用的Linux,安装过程中涉及操作系统的一些基础命令,如果命令不熟的话,会造成一定的困扰。如果配置加密传输的话,对于证书操作不理解,也会提升安装的难度。同样,框架集成这块,像Springboot这种框架是做了高度封装的,隐藏了很多细节,如果对框架低层不熟的话,也会加高使用的难度。

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

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

相关文章

【每日小技巧】如果Tomcat的端口被占用,怎么处理该报错

苦恼的问题&#xff1a;当我们在用Tomcat时&#xff0c;发现我们要用的端口被其他程序占用了&#xff0c;如图&#xff1a; 解决办法&#xff1a; ①winR&#xff0c;输入cmd&#xff0c;打开命令行 输入命令netstat -ano&#xff0c;列出所有的端口号使用情况 ②查看PID&#…

Linux命令_ps 进程管理

简介 ps通过读取 /proc 中的虚拟文件来工作&#xff0c;不需要 setuid kmem 或有任何特权来运行。 CPU使用率目前表示为进程整个生命周期中运行所花费时间的百分比。这是不理想的&#xff0c;它不符合ps在其他方面所符合的标准。CPU使用率加起来不太可能达到100%。 SIZE和RSS字…

E. DS哈希查找--Trie树

目录 题目描述 思路分析 AC代码 题目描述 Trie树又称单词查找树&#xff0c;是一种树形结构&#xff0c;如下图所示。 它是一种哈希树的变种。典型应用是用于统计&#xff0c;排序和保存大量的字符串&#xff08;但不仅限于字符串&#xff09;&#xff0c;所以经常被搜索引擎…

HTML列表与表格详解_高效学习攻略

HTML列表与表格HTML篇_第六章、HTML列表与表格一、列表1.1定义1.2列表的分类1.3列表的对比二、表格2.1表格的定义2.2表格的边框2.3表格的表头单元格2.4表格标题 <caption>2.5表格的高度和宽度2.6表格背景2.7表格空间2.8合并单元格2.9表格头部、主题和页脚2.10表格的嵌套H…

【C++常用容器】STL基础语法学习queue容器

目录 ●queue的基本概念 ●queue常用接口 ●构造函数 ●赋值操作 ●数据存取 ●大小操作 ●queue的基本概念 简要介绍&#xff1a;queue是一种先进先出的的数据结构&#xff0c;它有两个出口。队列容器允许从一端新增元素&#xff0c;从另一端移除元素。队列中只有队…

【Java基础篇】基础知识易错集锦(一)

在学习的路上&#xff0c;我们只记得学习新的知识&#xff0c;却忽略了一切新知识都是在旧知识的基础上&#xff1b;努力奔跑的过程中&#xff0c;也要记得常回头看看&#xff1b; 题目展示&#xff1a; 解析&#xff1a; abstract是抽象的意思&#xff0c;在java中&#xff0…

[附源码]计算机毕业设计的高校车辆租赁管理系统Springboot程序

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

SQL注入漏洞 | updatexml报错注入

文章目录前言MySQL updatexml报错注入前言 XML XML 被设计用来传输和存储数据&#xff0c;是各种应用程序之间进行数据传输的最常用的工具。 xpath XPath 是一门在 XML 文档中查找信息的语言。XPath 使用路径表达式来选取 XML 文档中的节点或者节点集。这些路径表达式和我们在…

【GRU回归预测】基于门控循环单元GRU实现数据多维输入单输出回归预测附matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;修心和技术同步精进&#xff0c;matlab项目合作可私信。 &#x1f34e;个人主页&#xff1a;Matlab科研工作室 &#x1f34a;个人信条&#xff1a;格物致知。 更多Matlab仿真内容点击&#x1f447; 智能优化算法 …

web期末大作业 使用HTML+CSS制作蓝色版爱宠之家带留言板(5页)

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

Redis 特性。

Remote Dict Serve 分类 实时同步数据 要求缓存中的数据必须与db中的数据保持一致&#xff0c;如何保证&#xff0c;只要DB发生了变化&#xff0c;缓存中的数据立即消息 阶段性缓存为了缓存数据 添加了生存时长属性 Redis 的特性。 性能极高 读的速度 11w/s 写的速度 8w次/s…

代码详细教程+文档+PPT+源码等]SSM框架美妆商城全套|电商购物计算机专业毕业论文java毕业设计网站

&#x1f496;&#x1f496;更多项目资源&#xff0c;最下方联系我们✨✨✨✨✨✨ 目录 Java项目介绍 资料获取 Java项目介绍 计算机毕业设计java毕设之SSM美妆商城项目源码_哔哩哔哩_bilibili项目资料网址: http://itzygogogo.com软件下载地址:http://itzygogogo.com/itsz…

详解Pytorch中的torch.nn.MSELoss函数(包括每个参数的分析)

一、函数介绍 Pytorch中MSELoss函数的接口声明如下&#xff0c;具体网址可以点这里。 torch.nn.MSELoss(size_averageNone, reduceNone, reduction‘mean’) 该函数默认用于计算两个输入对应元素差值平方和的均值。具体地&#xff0c;在深度学习中&#xff0c;可以使用该函数用…

《Linux运维实战:使用Percona Backup for MongoDB逻辑备份与恢复Mongodb数据》

一、备份与恢复方案 Percona Backup for MongoDB 是一个开源、分布式和低影响的解决方案&#xff0c;用于MongoDB分片集群和副本集的一致备份。从版本1.7.0开始&#xff0c;Percona Backup for MongoDB支持物理和逻辑备份和恢复&#xff0c;仅支持对逻辑备份进行时间点恢复。 …

Android.mk 入门学习

我们还是采用RK3399的开发板来学习Android.mk NOTED: 在编译之前&#xff0c;我们需要source & lunch source build/envsetup.sh lunch rk3399_roc_pc_plus-userdebug 或者lunch后选择41 一、Android.mk介绍 Android.mk是Android提供的一种makefile文件&#xff0c;用来指…

物理数据库服务器扫描hba卡识别共享磁盘命令

1、问题背景 默认情况&#xff0c;在扩容完1套物理rac共享存储后&#xff0c;rac主机是不能识别共享存储的。那么该怎么办呢&#xff1f; 2、解决办法 例如&#xff0c;在扩容完1套物理rac共享存储后&#xff0c;如果rac主机不能识别共享存储的话(一般需要执行命令后&#x…

HashMap1.8也会发生死循环—记录

目录 代码 jstack 分析 什么是哈希表 在讨论哈希表之前&#xff0c;我们先大概了解下其他数据结构在新增&#xff0c;查找等基础操作执行性能 数组&#xff1a;采用一段连续的存储单元来存储数据。对于指定下标的查找&#xff0c;时间复杂度为O(1)&#xff1b;通过给定值进…

代码随想录训练营day59, 下一个更大元素II, 接雨水

下一个更大元素II 给定一个循环数组, 输出每个元素的下一个更大元素, 没有则-1 所以在遍历的过程中, 模拟走了两遍nums class Solution {public int[] nextGreaterElements(int[] nums) {int len nums.length;//先进行边界判断if(nums null || len < 1){return new int…

Xinlei cheng报告学习

上面是 下面是momuten encoder 关键词 variance 方差 asymmetric不对称 momentum encoder 动量 dimension维度 convergence收敛 symmetrizationsy均衡 contrastive learning 对比学习 autoregressive自回归 distillation蒸馏 没有 fc layer +bn 裁剪后variance方差变大 cum…

[附源码]计算机毕业设计的黄河文化科普网站Springboot程序

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…