【Redis学习】Redis Docker安装,自定义config文件(包括RDB\AOF setup)以及与Spring Boot项目集成

【本文内容】

  • 第1章:通过Docker安装Redis,并自定义config文件以及mount data目录。
  • 第2章:介绍Redis持久化到磁盘,有4种方式:RDB / AOF / NONE / RDB + AOF
  • 第3章:使用Server自带的redis-cli工具连接。
  • 第4章:创建Spring Boot项目,通过spring-boot-starter-data-redis进行连接。
  • 第5章:把Spring Boot部署到docker中,测试docker network是否通畅。
  • 第6章:修改redis.conf,RDB持久化以及AOF持久化测试。

Redis全称:Remote Dictionary Server。是一款开源的Key-Value数据库,运行在内存中,由C语言编写。

官网:https://redis.com/

文档:https://redis.io/docs/getting-started/

Redis还有很多module:

image.png

很多公司用它用为缓存,也有用作database的,还有作为pub/sub(message broker)来使用。

1. Docker安装

关于Redis的安装,首先的还是Docker,这样可以和本机环境解耦,无论本机是windows, macos, linux,操作都会一样了。

【资源】

【参考】

如果到时候有app运行在docker中并要连接redis,那么可以先创建网络:

docker network create redis

1.1 简单的singleton模式

运行Docker:

docker run -it --rm --name redis --net redis -p 6379:6379 redis:latest

-it 表示run interactively,即通过/bin/bash与容器与行交互。
--rm 表示让容器在退出时,自动清除挂在的卷,以便清除数据。
-net 即运行在上述docker network create创建出来的网络中。
-p 端口,6379为默认端口,如果在远程服务器中,建议不要使用默认端口,主要原因是redis默认是不需要密码的。
redis:latest表示我们要运行的image=redis,版本为latest(最新版本)

可以看到下载的最新版本为7.0.2,单机版的redis已经运行了:

image.png

1.2 自定义config

Redis的核心配置是一个config文件,每个版本可能会不一样,可以从官网上查看:https://redis.io/docs/manual/config/

我们创建一个文件夹叫redis,在redis文件夹下创建文件夹config,在config中创建一个redis.conf文件,把7.0的config内容放进去:

image.png

在redis文件夹下,再次运行Docker,这次使用的是自定义的config

docker run -it --rm --name redis --net redis -v ${PWD}/config:/etc/redis/ redis:latest redis-server /etc/redis/redis.conf

${PWD}表示当前目录

这里做的是把我们刚刚创建的config目录,mount到docker容器中的/etc/redis/中,config file为/etc/redis/redis.conf,/etc/redis即刚刚mount的文件夹,即运行的redis使用的是我们上述自定义的redis.conf。

1.3 在redis.conf中启动security

我们上述说过不要在远程服务器中使用redis的默认端口的主要原因是redis默认是不需要密码登陆的,想要启用密码,可以在#1.2中创建的redis.conf中enable。

搜索关键字requirepass

image.png

可以看到默认情况下是不开启的:

image.png

启用需要密码并且把密码设为superpassword

image.png

安装redis的时候,可以考虑只在服务器集群内暴露,不要把它暴露到公网中,毕竟一般情况下只有集群内的app需要连接redis。

2. 持久化

持久化也是非常重要的一块内容,原因是上述的docker redis如果销毁了,存放在redis server上的数据也就没有了。

当然生产环境中一般不止一台redis server,假如有3台server,如果其中1台挂了,那么数据还是安全的,但如果3台server都挂了,存放在redis server内存中的数据也就没有了。

官网:https://redis.io/docs/manual/persistence/

Redis把数据写到磁盘的方式有:

  • RDB(Redis Database):RDB是以snapshot的方式记录当前的redis server的数据。比如每5分钟dump一个snapshot,存储到磁盘,文件为:dump.rdb。缺点是从最近一次dump到server挂了这段时间的数据会丢失。
  • AOF(Append Only File),将每次server接收的命令append到文件中,文件名叫appendonly.aof,这种方式在同步起来比较快(因为只要append最近的命令即可),但如果真的需要靠它来恢复数据,那么恢复起来就会比较慢一些。

官网详细的介绍了两者的优缺点:

除了可以单独选择使用其中的一种持久化方式,还可以选择不持久化,或是两者结合的方式

【以下是示例】

2.1 使用RDB的方式进行持久化

进入我们之前创建的redis.conf文件中,搜索关键字dump

image.png

可以看到redis默认支持的持久化就是RDB方式,除了可以修改dump后的文件名,我们还可以修改另的关于RDB的参数,如隔多久进行一次snapshot dump等等:

image.png

2.2 使用AOF的方式进行持久化

搜索关键字append

image.png

如果想要打开AOF持久化,可以把no改为yes

image.png

aof的文件名也可以修改:

image.png

2.3 如何选择?

参考官网:https://redis.io/docs/manual/persistence/#ok-so-what-should-i-use

  • The general indication you should use both persistence methods is if you want a degree of data safety comparable to what PostgreSQL can provide you.
  • If you care a lot about your data, but still can live with a few minutes of data loss in case of disasters, you can simply use RDB alone.
  • There are many users using AOF alone, but we discourage it since to have an RDB snapshot from time to time is a great idea for doing database backups, for faster restarts, and in the event of bugs in the AOF engine.

官网上说:

  • 如果想要保证数据的安全性,那么就可以同时打开RDB, AOF,即两者相结合的方式。
  • 如果可以容忍一小段时间的数据丢失,那么可以只开RDB(这里的一小段时间指的是RDB的snapshot dump到server down掉的时间)。
  • 有一些用户会只开启AOF,但不建议这样做,因为RDB是backup非常好的一种方式,它恢复数据会非常快,而AOF是基于事件的(即恢复数据靠的是重新run每个event/command),比较慢,而且中间万一哪个事件有点问题,就比较麻烦。
2.4 创建volumn开始做持久化测试

首先先创建一个volume叫redis:

docker volume create redis

在redis目录下创建data目录:

image.png

在redis目录下运行:

docker run -it --rm --name redis --net redis -p 6379:6379 -v {PWD}/data:/data/ redis:latest redis-server /etc/redis/redis.conf

这里我们看到除了mount 当前目录下的config文件夹至docker容器中外,还加了另一个文件夹,即/data。

以这样方式启动的docker redis,在重启后,里面的数据依然会在。

3. 使用Server自带的redis-cli工具连接

使用客户端连接,这里有很多可以选择:

  • server自带的cli命令可以操作数据
  • Java语言的话,可以使用Spring Boot框架可以很方便的连接到客户端
  • 当然别的语言也可以,python, go等

如果是使用客户端自带的cli工具,可以通过docker exec进入terminal页面,然后输入redis-cli即可,如果有设置过密码的,需要额外输入auth <password>

image.png

通过cli存放数据以及取出数据:

image.png

4. 使用Spring Boot项目进行连接

创建一个Spring Boot项目,依赖:

复制代码
<?xml version="1.0" encoding="UTF-8"?>
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.7</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
    </dependencies>
</project>

创建Main方法:

复制代码
@SpringBootApplication
public class RedisApplication {
    public static void main(String[] args) {
        SpringApplication.run(RedisApplication.class, args);
    }
}

在application.yaml加上:

复制代码
spring:
  redis:
    host: localhost
    port: 6379
    password: superpassword

创建一个Controller:

复制代码
@RestController
public class RedisTestController {

    @Autowired
    private RedisTemplate redisTemplate;

    @GetMapping("put")
    public boolean put(@RequestParam String key, @RequestParam String value) {
        ValueOperations<String, String> stringRedis = redisTemplate.opsForValue();
        stringRedis.set(key, value);
        return true;
    }

    @GetMapping("get")
    public String get(@RequestParam String key) {
        ValueOperations<String, String> stringRedis = redisTemplate.opsForValue();
        return stringRedis.get(key);
    }
}

启动后发现报错:

org.springframework.data.redis.RedisConnectionFailureException: Unable to connect to Redis; nested exception is io.lettuce.core.RedisConnectionException: Unable to connect to localhost:6379

at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$ExceptionTranslatingConnectionProvider.translateException(LettuceConnectionFactory.java:1689)
Caused by: io.lettuce.core.RedisConnectionException: Connection closed prematurely

at io.lettuce.core.protocol.RedisHandshakeHandler.channelInactive(RedisHandshakeHandler.java:86)

【需要修改redis.conf】

protected-mode yes:把yes改为no

image.png

还需要改下bind:

image.png

重启Redis和Spring Boot App后测试:

调用put:http://localhost:8080/put?key=testVersion&value=v1.0.0

image.png

get方法:

image.png

5. 把Spring Boot部署到docker中

5.1 Spring Boot相应改动

我们打算把Spring Boot项目和Redis放在同一个docker networ中,即在#1创建的redis中。

所以在application.yaml可以直接用redis来指代host:

复制代码
spring:
  redis:
    host: redis
    port: 6379
    password: superpassword

Spring Boot本身package出来的jar需要是可执行的fat jar,所以需要在pom.xml中加上:

复制代码
    <build>
        <finalName>RedisTest</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

mvn clean package打包,打出来的包在项目根目录/target/下。

5.2 再创建Docker file:
复制代码
FROM openjdk:8-jdk-alpine
COPY target/RedisTest.jar RedisTest.jar
expose 8080
ENTRYPOINT ["java","-jar","RedisTest.jar"]
5.3 Docker build image

DockerFile在项目根目录下:

docker build -f DockerFile -t localhost/redis-test .

5.4 运行Docker

这里8081指的是在docker外部即localhost的端口,8080指的是docker容器的端口:
docker run -p 8081:8080 --net redis --name redis-spring-test localhost/redis-test:latest

image.png

测试,没有问题:

image.png

5.5 Docker debug

如果出现connection refused的一些问题,可以进入Spring Boot的终端,然后ping下,看看是否通:
docker exec -it redis-spring-test /bin/sh

image.png

还可以查看#1中通过docker network create redis创建的network是否存在:

image.png

6. 测试持久化到磁盘

6.1 只开启RDB

我们在#2.1中介绍过,redis默认就是开启RDB的,只是dump的时间需要确定下,从redis.conf中可以看到,如不额外设置时间,默认情况下:

  • 只修改了1个key,1小时同步一次。
  • 修改了100个key,5分钟同步一次。
  • 修改了10000个key,那么1分钟同步一次。


image.png

为了测试我们可以把同步间隔设短的些,我们把修改1个key后就同步的时间从3600秒改成60秒:

image.png

用#3.4的命令重启Redis(即需要-v mount一个data的目录)后put一个key/value,过60s后check当前redis的data目录:

可以看到/data下有了dump.rdb文件了:

image.png

Redis控制台也会打印日志:

image.png

那么这时候如果我们把Docker Redis stop了再重启,可以看到会把从dump.rdb中恢复数据,然后这时候运行Spring Boot项目,依旧可以拿到key=testVersion的数据

image.png

6.2 只开启AOF

首先是关闭RDB:需要声明save ""

image.png

再开启AOF,如同#2.2说的,按append关键字搜索,然后把no改为yes:

image.png

可以看到对于AOF的同步,有三种方式,第1种是每一次修改,都会调用fsync()。第2种是每隔1秒调用fsync(),第3种是不调用fsync(),由系统控制数据的同步到磁盘。默认是每1各种调用fsync():

image.png

重启Redis后发现持久化已经由之前的RDB改成了AOF:

image.png

尝试set一个key/value后:

image.png

这时候关闭Redis再重启,可以看到数据会从AOF中恢复,直接get,数据依旧在:

image.png
最后编辑于:2025-02-24 20:46:46
© 著作权归作者所有,转载或内容合作请联系作者

喜欢的朋友记得点赞、收藏、关注哦!!!

相关推荐
这周也會开心3 分钟前
云服务器安装JDK、Tomcat、MySQL
java·服务器·tomcat
hrrrrb1 小时前
【Spring Security】Spring Security 概念
java·数据库·spring
小信丶1 小时前
Spring 中解决 “Could not autowire. There is more than one bean of type“ 错误
java·spring
sdgsdgdsgc1 小时前
Next.js企业级应用开发:SSR、ISR与性能监控方案
开发语言·前端·javascript
点灯小铭2 小时前
基于单片机的智能水箱温度液位控制系统设计
单片机·嵌入式硬件·毕业设计·课程设计
周杰伦_Jay2 小时前
【Java虚拟机(JVM)全面解析】从原理到面试实战、JVM故障处理、类加载、内存区域、垃圾回收
java·jvm
摇滚侠3 小时前
Spring Boot 3零基础教程,IOC容器中组件的注册,笔记08
spring boot·笔记·后端
rit84324995 小时前
基于MATLAB的模糊图像复原
开发语言·matlab
fie88895 小时前
基于MATLAB的声呐图像特征提取与显示
开发语言·人工智能
程序员小凯5 小时前
Spring Boot测试框架详解
java·spring boot·后端