【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}/config:/etc/redis/ -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
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,383评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,522评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,852评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,621评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,741评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,929评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,076评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,803评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,265评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,582评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,716评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,395评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,039评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,027评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,488评论 2 361
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,612评论 2 350

推荐阅读更多精彩内容