一个Redis的Java客户端Jedis的学习,线程不安全问题的解决及与MySQL的简单的结合

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 Tair(兼容Redis),内存型 2GB
简介: > Redis 全称 Remote Dictionary Server(即远程字典服务),它是一个基于内存实现的键值型非关系(NoSQL)数据库,由意大利人 Salvatore Sanfilippo 使用 C 语言编写。 > > Redis 遵守 BSD 协议,实现了免费开源,其最新版本是 6.20,常用版本包括 3.0 、4.0、5.0。自 Redis 诞生以来,它以其超高的性能、完美的文档和简洁易懂的源码广受好评,国内外很多大型互联网公司都在使用 Redis,比如腾讯、阿里、Twitter、Github 等等。简单的来说:Redis是一种极其高效的,迅速的一种基于缓存读写的N

什么是Redis

Redis 全称 Remote Dictionary Server(即远程字典服务),它是一个基于内存实现的键值型非关系(NoSQL)数据库,由意大利人 Salvatore Sanfilippo 使用 C 语言编写。

Redis 遵守 BSD 协议,实现了免费开源,其最新版本是 6.20,常用版本包括 3.0 、4.0、5.0。自 Redis 诞生以来,它以其超高的性能、完美的文档和简洁易懂的源码广受好评,国内外很多大型互联网公司都在使用 Redis,比如腾讯、阿里、Twitter、Github 等等。

简单的来说:Redis是一种极其高效的,迅速的一种基于缓存读写的NoSQL(非关系型数据库,另一种解释是:不仅仅是数据库---Not Only a SQL)

Redis为什么这么快

1.Redis完全基于内存,众所周知,内存的读写速度要远远超过硬盘。

2.非阻塞IO

  1. 单线程,不存在加锁释放锁的操作,不存在死锁(但可以同时开启多个Redis来发挥多核的优势)
  2. 编码规范,代码优美高效

三个很流行的Redis的Java客户端

1.Jedis

2.SpringDataRedis

3.Redisson

4.Lettuce

.......

Jedis的介绍

Jedis是基于java语言的redis客户端,集成了redis的命令操作,同时提供了连接池管理。

Jedis的优点及缺点

Jedis集成了Redis的命令操作,他提供了比较全面的 Redis 操作特性的 API,同时他的最大的门槛是相对其他主流的Redis的Java客户端他的门槛较低,较简单。但值得一提的是,Jedis同步阻塞 IO,
,不支持异步,而且它本身是一种线程不安全的方式,为解决线程不安全的问题需要线程池来进行连接。

Jedis的导入

传统的jar包导入

传统的jar导入并不多赘述,也不推荐。

众所周知,传统Jar包的导入即去对应的网址下载所需的jar包,然后放在指定的目录的下,但这么做有很多的问题与缺点

统jar包导入的缺点

首先要去找到对应的官网下的对应版本的jar包,有时候还会在浏览器主页中遇到很多的广告的网址,要去做一个筛选判断,而且即便找到了对应好的所需jar包的官网,繁重的英文,大量的不知道干什么的文件......

而且即便是找到了正确的资源jar包,较慢的下载速度,较为繁琐的引入方式,让人很难受。

Maven项目管理引入Jedis

这里我们采用Maven项目管理的方式来完成jar包的引入,这里的另一个好处是,传统的项目的创建,比如idea的项目,在eclipse上未必能运行。而采用Maven项目管理的方式,也一定程度上提高了项目的兼容性。同时在Maven项目中的pom.xml中直接导坐标的形式,一定程度上非常非常非常方便。

创建Maven工程基础的教程这里就不多赘述了

pom.xml中的依赖如下:

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>3.7.0</version>
</dependency>
<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter</artifactId>
    <version>5.7.0</version>
    <scope>test</scope>
</dependency>

这里分别引入了测试和redis.clients的jedis的3.7.0版本

通过new的方式使用Jedis

package com;


import Tools.JedisConnectionFactory;
import redis.clients.jedis.Jedis;

import java.util.stream.StreamSupport;

public class JedisDemo {
    private static Jedis jedis;

    public static void connectJedis(){
        jedis = new Jedis("127.0.0.1",6379);
        // password
        // select
        jedis.select(0);
    }

    public static void run(){
        String result = jedis.set("hobby","吃饭");
        System.out.println("result = "+result);
        String hobby = jedis.get("hobby");
        System.out.println("hobby is "+hobby);
    }

    public static void end(){
        if(jedis != null){
            jedis.close();
        }
    }

    public static void main(String[] args) {
        connectJedis();
        run();
        end();
    }
}

这里我们通过new Jedis(...)的方式完成Jedis的实例化。

如何我们分别定义了三个静态方法

  1. connectJedis()
  2. run()
  3. end()

分别是创立连接,执行命令和结束关闭销毁。

connectJedis()函数

new Jedis()中分别指定ip和端口

正常还需要在下一行提供密码,但是因为我们的redis没有设置密码,这里就不演示了。

run()函数

这里我们在run()函数中执行一些Redis的操作。

我们首先执行了set的操作

在redis中 set key value 可以向库中加入一个 键值对。

然后我们定义一个String result 来接收执行的结果。

然后我们下面又get了这个key(获取),

并通过 String hobby 来接受。

end()函数

在结束时,我们做了一个判断,如果jedis不为空(对象创立连接成功),就关闭销毁。

缺点

值得一提的是,Jedis本身是一种线程不安全的创建方式,这样做会导致线程不安全。

使用线程池建立连接

我们在java 目录下创立一个Tools目录,并创建一个 JedisConnectionFactory

代码如下:

package Tools;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

public class JedisConnectionFactory {
    private static final JedisPool jedisPool;
    static {
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        // 最大连接
        jedisPoolConfig.setMaxTotal(8);
        // 最大空闲连接
        jedisPoolConfig.setMaxIdle(8);
        // 最小空闲连接
        jedisPoolConfig.setMinIdle(0);
        // 设置最长等待时间
        jedisPoolConfig.setMaxWaitMillis(200);
        jedisPool = new JedisPool(jedisPoolConfig,"127.0.0.1",6379,1000);
    }
    public static Jedis getJedis() {
        return jedisPool.getResource();
    }
}

我们定义了一个JedisPool 类,然后在JedisConnectionFactory中写了一段静态方法(在类创建时执行一次且只执行一次)

最后写了一个getJedis()的方法用于对外通过反射连接到线程池中。

改变后的使用(JedisDemo)代码如下:

package com;


import Tools.JedisConnectionFactory;
import redis.clients.jedis.Jedis;

import java.util.stream.StreamSupport;

public class JedisDemo {
    private static Jedis jedis;

    public static void connectJedis(){
//        jedis = new Jedis("127.0.0.1",6379);
        jedis = JedisConnectionFactory.getJedis();
        // password
        // select
        jedis.select(0);
    }

    public static void run(){
        String result = jedis.set("hobby","吃饭");
        System.out.println("result = "+result);
        String hobby = jedis.get("hobby");
        System.out.println("hobby is "+hobby);
    }

    public static void end(){
        if(jedis != null){
            jedis.close();
        }
    }

    public static void main(String[] args) {
        connectJedis();
        run();
        end();
    }
}

可以看到,这里我们只是将原本的new 一个Jedis对象换成了通过我们封装在工具包下的工具类JedisConnectionFactory的类的getJedis()方法来以反射的形式创建这个Jedis对象。这样我们就解决了Jedis的线程不去安全的问题。

一个小项目的应用

看一个springboot中的应用,准备中正常创建静态代码块完成工厂,再通过反射获取Jedis实例,解决了线程连接不安全的问题,最后在接口中结合MySQL与Redis,完成查询的优化。

这里我们先在Redis中进行搜索,不存在的时候压力才会给到MySQL数据库,同时将结果一并存入Redis中,并设置过期时间,再次重复查询会直接通过Redis反馈结果。

@PostMapping("/JedisSelect")
@ResponseBody
public String JedisSelect(String name) {
    System.out.println(name);
    Jedis jedis = JedisConnectionFactory.getJedis();
    Docter docter = new Docter();
    String result = "";
    if (jedis.get(name) != null) {
        result = jedis.get(name);
    }
    else {
        docter = daoMapper.SelectDocter(name);
        if (docter != null) {
            jedis.set(name,JSON.toJSONString(docter));
            jedis.expire(name,1800);
        }
        result = JSON.toJSONString(docter);
    }
    if (jedis != null) {
        jedis.close();
    }
    System.out.println(result);
    return result;
}
相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
1月前
|
NoSQL 关系型数据库 MySQL
2024Mysql And Redis基础与进阶操作系列(4-2)作者——LJS[含MySQL非空、唯一性、PRIMARY KEY、自增列/自增约束举例说明等详解步骤及常见报错问题对应的解决方法]
24MySQL非空、唯一性、PRIMARY KEY、自增列/自增约束举例说明等详解步骤及常见报错问题对应的解决方法(4-2) 学不会你来砍我!!!
|
16天前
|
NoSQL Java 关系型数据库
Liunx部署java项目Tomcat、Redis、Mysql教程
本文详细介绍了如何在 Linux 服务器上安装和配置 Tomcat、MySQL 和 Redis,并部署 Java 项目。通过这些步骤,您可以搭建一个高效稳定的 Java 应用运行环境。希望本文能为您在实际操作中提供有价值的参考。
89 26
|
2天前
|
NoSQL 关系型数据库 MySQL
Linux安装jdk、mysql、redis
Linux安装jdk、mysql、redis
53 7
|
3天前
|
SQL 关系型数据库 MySQL
MySQL操作利器大公开!这几款客户端让你事半功倍
本文介绍了多种MySQL数据库管理工具,包括命令行工具、图形化用户界面(GUI)工具和Web界面工具。主要工具有: 1. **Navicat for MySQL**:功能强大,支持多种数据库管理任务,但需付费。 2. **DBeaver**:开源免费,支持多种数据库,安装包较大。 3. **MySQL Workbench**:官方提供的图形化工具,适合MySQL全家桶用户。 4. **HeidiSQL**:轻量级Windows客户端,简单易用。 5. **phpMyAdmin**:基于Web的管理工具,易于部署和使用。 6. **SQLyog**:适用于Windows,功能丰富,有免费
15 3
|
20天前
|
JavaScript 安全 Java
java版药品不良反应智能监测系统源码,采用SpringBoot、Vue、MySQL技术开发
基于B/S架构,采用Java、SpringBoot、Vue、MySQL等技术自主研发的ADR智能监测系统,适用于三甲医院,支持二次开发。该系统能自动监测全院患者药物不良反应,通过移动端和PC端实时反馈,提升用药安全。系统涵盖规则管理、监测报告、系统管理三大模块,确保精准、高效地处理ADR事件。
|
1月前
|
缓存 NoSQL 关系型数据库
Redis和Mysql如何保证数据⼀致?
在项目中,为了解决Redis与Mysql的数据一致性问题,我们采用了多种策略:对于低一致性要求的数据,不做特别处理;时效性数据通过设置缓存过期时间来减少不一致风险;高一致性但时效性要求不高的数据,利用MQ异步同步确保最终一致性;而对一致性和时效性都有高要求的数据,则采用分布式事务(如Seata TCC模式)来保障。
67 14
|
1月前
|
关系型数据库 MySQL Java
MySQL索引优化与Java应用实践
【11月更文挑战第25天】在大数据量和高并发的业务场景下,MySQL数据库的索引优化是提升查询性能的关键。本文将深入探讨MySQL索引的多种类型、优化策略及其在Java应用中的实践,通过历史背景、业务场景、底层原理的介绍,并结合Java示例代码,帮助Java架构师更好地理解并应用这些技术。
32 2
|
1月前
|
存储 NoSQL 关系型数据库
MySQL和Redis的区别
**MySQL和Redis的区别** MySQL和Redis都是流行的数据存储解决方案,但它们在设计、用途和特性上有显著区别。理解这些区别有助于选择合适的数据库来满足不同的应用需求。本文将详细介绍MySQL和Redis的区别,包括它们的架构、使用场景、性能和其他关键特性。 ### 一、基本概述 **MySQL**: MySQL是一个关系型数据库管理系统(RDBMS),使用结构化查询语言(SQL)进行数据管理。它支持事务、复杂查询和多种存储引擎,广泛应用于各种Web应用、企业系统和数据分析项目。 **Redis**: Redis是一个基于内存的键值数据库,通常被称为NoSQL数
86 4
|
1月前
|
监控 前端开发 Java
【技术开发】接口管理平台要用什么技术栈?推荐:Java+Vue3+Docker+MySQL
该文档介绍了基于Java后端和Vue3前端构建的管理系统的技术栈及功能模块,涵盖管理后台的访问、登录、首页概览、API接口管理、接口权限设置、接口监控、计费管理、账号管理、应用管理、数据库配置、站点配置及管理员个人设置等内容,并提供了访问地址及操作指南。
|
1月前
|
存储 消息中间件 NoSQL
使用Java操作Redis数据类型的详解指南
通过使用Jedis库,可以在Java中方便地操作Redis的各种数据类型。本文详细介绍了字符串、哈希、列表、集合和有序集合的基本操作及其对应的Java实现。这些示例展示了如何使用Java与Redis进行交互,为开发高效的Redis客户端应用程序提供了基础。希望本文的指南能帮助您更好地理解和使用Redis,提升应用程序的性能和可靠性。
41 1