前言
Redis 简介&排名
Redis,我想大家应该都不陌生,Redis 是一款开源的高性能键值对存储系统,具有快速、灵活和可扩展的特性。它是一个基于内存的数据结构存储系统,可以用作数据库、缓存和消息代理等。
目前在DB-Engines的排名中,Redis 是Key-Value类型排名第一,所有数据库类型排名第6的产品。大家可以点击下方的链接查看当前最新的排名。
DB-Engines Ranking
开发人员必备组件
Redis 是一款功能强大且易于使用的数据库,它已经成为许多应用程序的核心组件。作为一个开发人员,日常工作中很大可能性都会要用到Redis这个组件。一个典型的互联网应用的架构应该如下图所示:
在高并发的互联网应用中,Redis 作为缓存,介于数据库和应用之间,起到了缓冲的作用。得益于Redis是内存型数据库,其访问速度是微秒级,甚至是纳秒级的,据Redis官方数据,其 QPS(每秒查询数)可以达到约 100 万次,所以采用Redis可以显著的提高互联网应用的响应速度。
Redis的安装
作为一名开发人员,如果正在学习在自己的应用里使用Redis这个组件,首先我们得搭建一个Redis环境。当然我们也可以绕过这个过程,直接购买和使用公有云上的Redis产品,或者使用公司私有云平台提供的Redis服务。
本文的主要目的是带大家了解几种不同的安装方式,大家可以自己动手实践一下,也方便后续我们可以在自己的环境里进行各种Redis的操作和练习,即使把Redis整崩溃了也不会带来什么影响。
通过Docker安装部署Redis单实例(推荐)
如果想通过Docker来安装部署Redis, 我们首先要在自己的操作系统上安装Docker运行时环境,可以参考我写的另两篇文章
如果已经安装了Docker环境,就可以按以下步骤来部署一个Redis单实例服务了
- STEP1、拉取redis镜像
docker pull redis
-
STEP2、基于redis基础镜作一些小修改
为了方便在宿主机上查看Redis日志,我们会将容器中的/data目录映射到本地目录,而redis基础镜像中只有/data目录,我们需要在 /data/目录下创建子目录用来存储Redis日志。
比如:/data/log/redis/- 准备Dockerfile,保存在~/ws/redis目录下
- 在~/ws/redis目录下执行docker build命令
#Dockerfile
FROM redis
RUN mkdir /data/log
RUN mkdir /data/log/redis
#基于Dockerfile创建新的Redis镜像
#在~/ws/redis目录下扫行如下命令
#原来的redis:latest会变成redis:<none>
#新的镜像将变成:redis:latest
docker build -t redis .
[+] Building 0.3s (9/9) FINISHED docker:default
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 141B 0.0s
=> [internal] load metadata for docker.io/library/redis:latest 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [1/3] FROM docker.io/library/redis:latest 0.0s
=> CACHED [2/3] RUN mkdir /data/log 0.0s
=> CACHED [3/3] RUN mkdir /data/log/redis 0.0s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:66cc2db5ff3027131f181663418a5f6b4efe8017fb80204af18446dd879e3c3a 0.0s
=> => naming to docker.io/library/redis
- STEP3、准备Redis配置文件
- 复制以下内容,在保存为:~/ws/redis/redis.conf
daemonize no
#这里是容器的/data/log/redis目录,已经通过自定义镜像创建
logfile /data/log/redis/redis.log
loglevel notice
databases 16
bind 0.0.0.0
port 6379
protected-mode no
tcp-keepalive 0
timeout 300
save 900 1
save 300 10
save 60 10000
appendonly no
dbfilename dump.rdb
dir /data/
maxclients 10000
maxmemory 209715200
maxmemory-policy volatile-lru
requirepass "helloworld"
slowlog-log-slower-than 10000
slowlog-max-len 10000
- STEP4 准备本地数据目录
我们在~ws/redis目录下,创建data目录,并创建log/redis子目录,如下所示:
vian@txzq1899-ubuntu:~/ws/redis$ ll
总计 24
drwxrwxr-x 3 vian vian 4096 5月 3 15:47 ./
drwxrwxr-x 7 vian vian 4096 5月 3 15:45 ../
drwxr-xr-x 3 999 root 4096 5月 3 15:47 data/
-rw-rw-r-- 1 vian vian 104 5月 3 15:11 Dockerfile
-rw-rw-r-- 1 vian vian 376 5月 3 15:47 redis.conf
-rwxrwxr-x 1 vian vian 257 5月 3 15:46 singleRedis.sh*
vian@txzq1899-ubuntu:~/ws/redis$ tree
.
├── data
│ ├── dump.rdb
│ └── log
│ └── redis
│ └── redis.log
├── Dockerfile
├── redis.conf
└── singleRedis.sh
3 directories, 5 files
vian@txzq1899-ubuntu:~/ws/redis$
- STEP5、编写singleRedis.sh,用于启动一个Redis实例
docker run -it -d -p 6379:6379 \
--privileged=true \
-v ~/ws/redis/redis.conf:/usr/local/etc/redis/redis.conf \
-v ~/ws/redis/data:/data \
--restart always --name redis-6379 \
--sysctl net.core.somaxconn=1024 \
redis redis-server /usr/local/etc/redis/redis.conf
- STEP6、修改singleResis.sh的执行权限
chmod +x singleRedis.sh
#执行脚本,启动Redis容器
./singleRedis.sh
#查看redis容器
vian@txzq1899-ubuntu:~/ws/redis$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ab9fb216bd35 redis "docker-entrypoint.s…" 7 seconds ago Up 5 seconds 0.0.0.0:6379->6379/tcp, :::6379->6379/tcp redis-6379
- STEP7、验证Redis服务
docker exec -it redis-6379 bash
#执行上面的命令,将进入容器
root@ab9fb216bd35:/data#
#连接Redis服务,helloworld 是密码,在redis.conf中配置
#-a helloworld, 表示通过密码登录
root@ab9fb216bd35:/data# redis-cli -a helloworld
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:6379>
#输入info Server获取Redis服务器相关信息
127.0.0.1:6379> info Server
# Server
redis_version:7.2.4
redis_git_sha1:00000000
redis_git_dirty:0
redis_build_id:2a5e82a4865cf90d
redis_mode:standalone
os:Linux 6.5.0-28-generic x86_64
arch_bits:64
monotonic_clock:POSIX clock_gettime
multiplexing_api:epoll
atomicvar_api:c11-builtin
gcc_version:12.2.0
process_id:1
process_supervised:no
run_id:c58bf3931ad45ac90072640b569798bfd7cd7cc2
tcp_port:6379
server_time_usec:1714723327461977
uptime_in_seconds:381
uptime_in_days:0
hz:10
configured_hz:10
lru_clock:3447295
executable:/data/redis-server
config_file:/usr/local/etc/redis/redis.conf
io_threads_active:0
listener0:name=tcp,bind=0.0.0.0,port=6379
一台基于Docker容器的单实例Redis服务就已经成功部署。
我们就可以通过RedisInsight连接到该Redis服务上
通过源码编译和部署Redis单实例(不推荐)
另外一种部署Redis单实例的方式就是在官网上下载源代码,通过make来编译Redis,但该方法不太推荐。因为Redis的编译需要本机有C语言环境,和其它的一些依赖库。每个小伙伴的操作系统环境不一样,可能安装时遇到的问题也不太一样,以下步骤仅供参考,如有遇到其它问题,还需自行查找解决方法。
- STEP1、下载源代码压缩包,并解压
wget https://download.redis.io/redis-stable.tar.gz
--2024-05-03 08:18:17-- https://download.redis.io/redis-stable.tar.gz
Resolving download.redis.io (download.redis.io)... 45.60.125.1
Connecting to download.redis.io (download.redis.io)|45.60.125.1|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 3479614 (3.3M) [application/octet-stream]
Saving to: 'redis-stable.tar.gz'
redis-stable.tar.gz 100%[=====================================================================================================================>] 3.32M 1.88MB/s in 1.8s
2024-05-03 08:18:20 (1.88 MB/s) - 'redis-stable.tar.gz' saved [3479614/3479614]
tar -xzvf redis-stable.tar.gz
- STEP2、准备Redis的编译环境
Redis 依赖C++,依赖make, pkg-config等,如果本地环境没有安装gcc, make, pkg-config等组件,我们在执行make时,可能遇到下面的错误信息
#没有安装make时,会出现如下错误
make
bash: make: command not found
#安装make后,可能遇到如下错误:
root@6fc860cf0f14:/home/redis-stable# make
cd src && make all
make[1]: Entering directory '/home/redis-stable/src'
sh: 1: cc: not found
/bin/sh: 1: pkg-config: not found
/bin/sh: 1: pkg-config: not found
/bin/sh: 1: pkg-config: not found
所以我们需要准备好Redis编译所需要的依赖项:make, gcc, pkg-config, libjemalloc-dev
sudo apt update
sudo apt install make gcc pkg-config libjemalloc-dev
- STEP3 执行make
-
如果在执行make的过程中,出现了其它的问题,比如说某个依赖包不在,我们需要安装相应的依赖包,然后重新make.
-
如果依赖包安装好,依然make不通过,建议删除redis-stable目录,重新解压后,重新进行make操作。
-
cd redis-stable
make
#整个过程会比较久,也可能会出现其它的一些错误,但基本上都是缺少一些库,需要安装相应的库
#如果看到以下结果:表示已经编译成功了。
CC unix.o
CC logreqres.o
LINK redis-server
lto-wrapper: warning: using serial compilation of 31 LTRANS jobs
INSTALL redis-sentinel
CC redis-cli.o
CC redisassert.o
CC cli_common.o
CC cli_commands.o
LINK redis-cli
lto-wrapper: warning: using serial compilation of 4 LTRANS jobs
CC redis-benchmark.o
LINK redis-benchmark
lto-wrapper: warning: using serial compilation of 2 LTRANS jobs
INSTALL redis-check-rdb
INSTALL redis-check-aof
Hint: It's a good idea to run 'make test' ;)
make[1]: Leaving directory '/home/redis-stable/src'
- STEP4、部署Redis-Server
#执行 make install命令
root@6fc860cf0f14:/home/redis-stable# make install
cd src && make install
make[1]: Entering directory '/home/redis-stable/src'
CC Makefile.dep
Hint: It's a good idea to run 'make test' ;)
INSTALL redis-server
INSTALL redis-benchmark
INSTALL redis-cli
make[1]: Leaving directory '/home/redis-stable/src'
root@6fc860cf0f14:/home/redis-stable#
- STEP5、测试启动Redis-Server
oot@6fc860cf0f14:/home/redis-stable# redis-server
7519:C 03 May 2024 08:46:49.102 # WARNING Memory overcommit must be enabled! Without it, a background save or replication may fail under low memory condition. Being disabled, it can also cause failures without low memory condition, see https://github.com/jemalloc/jemalloc/issues/1328. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
7519:C 03 May 2024 08:46:49.103 * oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
7519:C 03 May 2024 08:46:49.103 * Redis version=7.2.4, bits=64, commit=00000000, modified=0, pid=7519, just started
7519:C 03 May 2024 08:46:49.103 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
7519:M 03 May 2024 08:46:49.107 * monotonic clock: POSIX clock_gettime
_._
_.-``__ ''-._
_.-`` `. `_. ''-._ Redis 7.2.4 (00000000/0) 64 bit
.-`` .-```. ```\/ _.,_ ''-._
( ' , .-` | `, ) Running in standalone mode
|`-._`-...-` __...-.``-._|'` _.-'| Port: 6379
| `-._ `._ / _.-' | PID: 7519
`-._ `-._ `-./ _.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' | https://redis.io
`-._ `-._`-.__.-'_.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' |
`-._ `-._`-.__.-'_.-' _.-'
`-._ `-.__.-' _.-'
`-._ _.-'
`-.__.-'
7519:M 03 May 2024 08:46:49.111 * Server initialized
7519:M 03 May 2024 08:46:49.112 * Ready to accept connections tcp
到这里,通过源码编译的Redis-Server就已经部署好了,类似于容器的启动方式,我们可以通过 redis-server /etc/redis/conf/redis.conf 来通过自定义配置文件来启动Redis.
通过Docker安装部署Redis-Cluster高可用集群(推荐)
如果小伙伴们已经能通过第一种方式成功部署好一个单实例的Redis服务器,那么要通过Docker搭建一个Redis-Cluster就非常简单了。
Redis Cluster 架构
一个高可用的Redis-Cluster 集群,包含3主3从,6个节点,如上图所示。
因为我们是在一台Docker宿主机上模拟3主3从,实际上是达不到真正的集群高可用的,实际的生产环境,一般是在Kubernetes集群中部署,6个节点会分散在6台不同的物理宿机上,以保证集群在单机房的高可用,这里请大家注意一下。
准备工作
- 由于是在一台Docker宿主机上,所以6个容器节点对外暴露的端口号依次是
服务端口(主机 -> 容器) | 通讯端口 (主机 -> 容器) |
---|---|
6379 -> 6379 | 16379 -> 16379 |
6380 -> 6379 | 16380 -> 16379 |
6381 -> 6379 | 16381 -> 16379 |
6382 -> 6379 | 16382 -> 16379 |
6383 -> 6379 | 16383 -> 16379 |
6384 -> 6379 | 16384 -> 16379 |
- 端口不同,配置文件也有所不同,
redis.conf文件模板如下,以下有专门的脚本来准备配置文件
port 6379
requirepass "helloworld"
bind 0.0.0.0
protected-mode no
daemonize no
appendonly no
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip 192.168.0.111 #宿主机IP
cluster-announce-port 6379 #第二,第三至第六,分别是:6380,6381...6384
cluster-announce-bus-port 16379 #第二,第三至第六,分别是:16380,16381...16384
- 创建redis-cluster容器网络
我们需要在Docker主机中新建一个redis-cluster的容器网络,使得我们可以在一个subnet下创建这6个Redis节点。
docker network create redis-cluster
- 准备配置文件批量创建脚本 : redisconf.sh
for sn in $(seq 1 6);
do
port=$((6378+sn))
mkdir -p ~/ws/redis-cluster/node-${sn}/conf
touch ~/ws/redis-cluster/node-${sn}/conf/redis.conf
cat << EOF > ~/ws/redis-cluster/node-${sn}/conf/redis.conf
port 6379
requirepass "helloworld"
bind 0.0.0.0
protected-mode no
daemonize no
appendonly no
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip 192.168.0.111
cluster-announce-port ${port}
cluster-announce-bus-port 1${port}
EOF
done
- 准备批量启动redis容器脚本 : start-cluster.sh
for sn in $(seq 1 6); \
do \
port=$((sn+6378))
docker run -it -d -p ${port}:6379 -p 1${port}:16379 \
--privileged=true \
-v ~/ws/redis-cluster/node-${sn}/conf/redis.conf:/usr/local/etc/redis/redis.conf \
-v ~/ws/redis-cluster/redis/node-${sn}/data:/data \
--restart always --name redis-${sn} --net redis-cluster \
--sysctl net.core.somaxconn=1024 redis redis-server /usr/local/etc/redis/redis.conf
done
- 准备批量停止redis容器脚本 : stop-cluster.sh
for sn in $(seq 1 6); \
do \
docker stop redis-${sn}
done
- 准备批量删除redis容器脚本 : remove-cluster.sh
for sn in $(seq 1 6); \
do \
docker rm redis-${sn}
done
创建并启动集群
- STEP1、创建配置文件
./redisconf.sh
- STEP2、批量启动容器
./start-cluster.sh
- STEP3、获取容器IP
docker network inspect redis-cluster | grep IPv4
"IPv4Address": "172.19.0.2/16",
"IPv4Address": "172.19.0.5/16",
"IPv4Address": "172.19.0.6/16",
"IPv4Address": "172.19.0.4/16",
"IPv4Address": "172.19.0.3/16",
"IPv4Address": "172.19.0.7/16",
- STEP4、建立集群
- 执行命令:docker exec -it redis-1 bash,进入容器redis-1
- 执行命令:redis-cli -a helloworld --cluster create
redis-cli -a helloworld --cluster create \ 172.19.0.2:6379 172.19.0.3:6379 172.19.0.4:6379 \ 172.19.0.5:6379 172.19.0.6:6379 172.19.0.7:6379 \ --cluster-replicas 1
#进入Redis-1容器
vian@txzq1899-ubuntu:~/ws/redis-cluster$ docker exec -it redis-1 bash
#集群初始化
root@12b3f9449025:/data# redis-cli -a helloworld --cluster create 172.19.0.2:6379 172.19.0.3:6379 172.19.0.4:6379 172.19.0.5:6379 172.19.0.6:6379 172.19.0.7:6379 --cluster-replicas 1
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 172.19.0.6:6379 to 172.19.0.2:6379
Adding replica 172.19.0.7:6379 to 172.19.0.3:6379
Adding replica 172.19.0.5:6379 to 172.19.0.4:6379
M: cf5142968a7298a83c5a122a1a31c73cb1af554f 172.19.0.2:6379
slots:[0-5460] (5461 slots) master
M: a0f408033b796ea118b3768cc06007a3a0a50198 172.19.0.3:6379
slots:[5461-10922] (5462 slots) master
M: 2e44a533a7fd6d266f4a9406841c72acbe880491 172.19.0.4:6379
slots:[10923-16383] (5461 slots) master
S: 1ae90df7031f4375f5d51ec763936b1e9348796d 172.19.0.5:6379
replicates 2e44a533a7fd6d266f4a9406841c72acbe880491
S: 5e95145570f5941775686f797d39858fd110dbba 172.19.0.6:6379
replicates cf5142968a7298a83c5a122a1a31c73cb1af554f
S: 87b5c1bca695719e7c91ec3564b559f6cc02cffa 172.19.0.7:6379
replicates a0f408033b796ea118b3768cc06007a3a0a50198
Can I set the above configuration? (type 'yes' to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join
>>> Performing Cluster Check (using node 172.19.0.2:6379)
M: cf5142968a7298a83c5a122a1a31c73cb1af554f 172.19.0.2:6379
slots:[0-5460] (5461 slots) master
1 additional replica(s)
S: 5e95145570f5941775686f797d39858fd110dbba 192.168.0.111:6383
slots: (0 slots) slave
replicates cf5142968a7298a83c5a122a1a31c73cb1af554f
S: 87b5c1bca695719e7c91ec3564b559f6cc02cffa 192.168.0.111:6384
slots: (0 slots) slave
replicates a0f408033b796ea118b3768cc06007a3a0a50198
M: a0f408033b796ea118b3768cc06007a3a0a50198 192.168.0.111:6380
slots:[5461-10922] (5462 slots) master
1 additional replica(s)
S: 1ae90df7031f4375f5d51ec763936b1e9348796d 192.168.0.111:6382
slots: (0 slots) slave
replicates 2e44a533a7fd6d266f4a9406841c72acbe880491
M: 2e44a533a7fd6d266f4a9406841c72acbe880491 192.168.0.111:6381
slots:[10923-16383] (5461 slots) master
1 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
那么一个简单的Reids-Cluster就搭建成功了。
总结
根据本文的指引和操作步骤,想在自己的电脑上部署一个Redis服务基本上就没问题了,大家可以写自己的应用程序和Redis交互了。
其实如果想在Docker主机上运行一个Redis-Cluster,还有其它的方式,比如Docker-Compose,大家可以自行查找相关资料,通过自我实践来部署一个Redis-Cluster。
关注我的公众号
欢迎大家关注我的公众号,一起交流软件开发、架构设计、云原生技术