【编者的话】本文介绍了如何使用Docker搭建Redis集群,很多读者都在问Docker能带来哪些实质性的好处,我想本文就是一个很好的例子。不使用Docker你也可以搭建Redis集群,那使用Docker后会有怎么样的优势了?我想可以用两个词总结:快速和复用。
我们经常会遇到这样一个问题:当我们想进行一个完整的测试的时候,往往缺少硬件或者其它资源。为了满足需求,我可能需要三台服务,或者说三个虚拟机。但是我发现我们没有时间来创建它们,并且如果要物理机的话我们也没有那么多资源。这也是为什么我对Docker如此感兴趣,因为它可以解决我的问题。
我想在Ubuntu上创建三个运行Redis的Docker容器,并把它们连接起来,然后我就可以自由的在测试和开发过程中水平的扩展了, 接下来我就给你们展示我是怎么做的,以及这样做的优势。
1. 下载和配置基础镜像
我使用的是非常优秀的phusion镜像作为基础镜像,它增加了很多Docker忽略的特性, 比如按序启动服务等等, 关于这个镜像的更多信息,可以点击这里了解。
首先,让我们使用Docker来pullphusion镜像(译者注:建议使用高版本的Docker下载,低版本会有问题)。
docker pull phusion/baseimage
下载完成之后, 你可以通过docker images命令看到最新下载的镜像。
docker images REPOSITORY TAG IMAGE ID CREATE D SIZE docker.io/phusion/baseimage latest 166cfc3f6974 5 mont hs ago 209 MB docker.io/curiousby/centos-ssh-root-java-tomcat-maven-nexus-svn original 358f17fad349 8 mont hs ago 1.17 GB docker.io/curiousby/centos-ssh-root-java-tomcat-maven-nexus original eb7293ef9028 8 mont hs ago 1.01 GB
这个镜像非常好用,你可以在容器启动的时候指定特定服务的启动顺序, 在这里我想给这个镜像加一个SSH密码登录的功能,而不是使用SSH key。因为是在本地运行,所以不用太担心安全的问题。我们需要创建一个phusion的实例, 然后通过SSH key登录, 并且修改配置,重启SSH,之后我们就可以使用root登录了。
首先,用phusion基础镜像创建一个新的容器。
docker run -d --name redis phusion/baseimage /sbin/my_init --enable-insecure-key
/sbin/my_init是允许phusion在容器启动的时候启动你的服务。 enable-insecure-key允许我们使用‘insecure key‘ssh进新的容器。
现在我们已经部署了容器, 接下来需要得到它的IP地址,可以使用docker inspect命令
docker inspect redis | grep IPA "SecondaryIPAddresses": null, "IPAddress": "172.17.0.2", "IPAMConfig": null, "IPAddress": "172.17.0.2",
接下来,下载’insecure key‘并使用它登录这个容器。
curl -o insecure_key -fSL https://github.com/takei-yuya/insecure_public_key/blob/master/insecure_key.pub
下载insecure_key到当前目录后,修改权限
chmod 600 insecure_key [root@svn sam]# ls -l 总用量 64 -rw------- 1 root root 64127 7月 22 18:20 insecure_key
[root@svn sam]# ifconfig docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 172.17.0.1 netmask 255.255.0.0 broadcast 0.0.0.0 inet6 fe80::42:39ff:fef4:bed8 prefixlen 64 scopeid 0x20<link> ether 02:42:39:f4:be:d8 txqueuelen 0 (Ethernet) RX packets 33 bytes 2076 (2.0 KiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 21 bytes 2228 (2.1 KiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 ens192: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 10.0.100.210 netmask 255.255.255.0 broadcast 10.0.100.255 inet6 fe80::8815:e9b3:1b5a:faee prefixlen 64 scopeid 0x20<link> ether 00:50:56:ae:73:2c txqueuelen 1000 (Ethernet) RX packets 821955 bytes 143646869 (136.9 MiB) RX errors 0 dropped 72 overruns 0 frame 0 TX packets 557848 bytes 41166593 (39.2 MiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536 inet 127.0.0.1 netmask 255.0.0.0 inet6 ::1 prefixlen 128 scopeid 0x10<host> loop txqueuelen 1 (Local Loopback) RX packets 2 bytes 196 (196.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 2 bytes 196 (196.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 veth9e19302: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet6 fe80::d4a2:7dff:fe37:fe07 prefixlen 64 scopeid 0x20<link> ether d6:a2:7d:37:fe:07 txqueuelen 0 (Ethernet) RX packets 13 bytes 882 (882.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 13 bytes 922 (922.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 virbr0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500 inet 192.168.122.1 netmask 255.255.255.0 broadcast 192.168.122.255 ether 52:54:00:e9:c4:8a txqueuelen 1000 (Ethernet) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 0 bytes 0 (0.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 [root@svn sam]# ssh -i insecure_key root@10.0.100.210 The authenticity of host '10.0.100.210 (10.0.100.210)' can't be established. ECDSA key fingerprint is SHA256:LRjdi8K/ZLedi3BtvuLkY8E7QOQs5kz7/DUeglehNc0. ECDSA key fingerprint is MD5:66:1c:7f:93:06:d7:d9:4a:5a:d8:1d:eb:77:6b:9f:8c. Are you sure you want to continue connecting (yes/no)?
[root@svn sam]# ssh -i insecure_key root@10.0.100.210 Enter passphrase for key 'insecure_key': Enter passphrase for key 'insecure_key': Enter passphrase for key 'insecure_key': root@10.0.100.210's password: Last login: Sun Jul 22 16:54:11 2018 from 10.0.10.69
祝贺你, 你现在SSH进入容器了!下面你需要修改SSH,从而我们不再需要’insecure key‘了,为了做到这个,打开’/etc/ssh/sshd_config‘找到下面这一行, 并去掉注释
PermitRootLogin yes
保存文件, 我们再设置root的密码。
passwd 更改用户 root 的密码 。 新的 密码: 重新输入新的 密码: passwd:所有的身份验证令牌已经成功更新。 [root@svn ~]#
以上我们做了一些准备工作,接下来我们将在这个容器中安装Redis。
docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 8e044161c998 phusion/baseimage "/sbin/my_init --e..." 37 minutes ago Up 37 minutes redis c1e4909a8f60 curiousby/centos-ssh-root-java-tomcat-maven-nexus-svn:original "/usr/local/nexus/..." 4 months ago Exited (255) About an hour ago 0.0.0.0:3690->3690/tcp, 22/tcp, 0.0.0.0:8080-8081->8080-8081/tcp docker1
首先启动我们刚才创建的容器
docker start 8e044161c998
进入容器中
docker exec -it 8e044161c998 /bin/bash
下载redis到容器中
wget https://github.com/antirez/redis/archive/3.0.0-rc1.tar.gz bash: wget: command not found
发现wget这个命令不存在,这个时候,我们需要升级系统,然后安装wget命令
apt-get update #更新系统 apt-get upgrade #升级系统 apt-get install wget gcc make#安装wget、gcc、make
然后我们在下载Redis 3.0.0 RC1
wget https://github.com/antirez/redis/archive/3.0.0-rc1.tar.gz --2018-07-22 10:46:46-- https://github.com/antirez/redis/archive/3.0.0-rc1.tar.gz Resolving github.com (github.com)... 13.229.188.59, 13.250.177.223, 52.74.223.119 Connecting to github.com (github.com)|13.229.188.59|:443... connected. HTTP request sent, awaiting response... 302 Found Location: https://codeload.github.com/antirez/redis/tar.gz/3.0.0-rc1 [following] --2018-07-22 10:46:49-- https://codeload.github.com/antirez/redis/tar.gz/3.0.0-rc1 Resolving codeload.github.com (codeload.github.com)... 13.250.162.133, 54.251.140.56, 13.229.189.0 Connecting to codeload.github.com (codeload.github.com)|13.250.162.133|:443... connected. HTTP request sent, awaiting response... 200 OK Length: unspecified [application/x-gzip] Saving to: ‘3.0.0-rc1.tar.gz’ 3.0.0-rc1.tar.gz [ <=> ] 1.27M 649KB/s in 2.0s 2018-07-22 10:46:53 (649 KB/s) - ‘3.0.0-rc1.tar.gz’ saved [1335857]
移动刚下载的包到home目录下
ls 3.0.0-rc1.tar.gz bin dev home lib64 mnt proc run srv tmp var bd_build boot etc lib media opt root sbin sys usr root@8e044161c998:/# mv 3.0.0-rc1.tar.gz home/ root@8e044161c998:/# cd home/ root@8e044161c998:/home# ls 3.0.0-rc1.tar.gz
解压这个包并make。
tar -zxvf 3.0.0-rc1.tar.gz
进入到刚刚解压的目录
cd redis-3.0.0-rc1/ root@8e044161c998:/home/redis-3.0.0-rc1#
执行make
make
最后, 我们把编译好的代码中的几个可执行命令移动到/usr/bin/下面
root@e3919192d9e3:/home/redis-3.0.0-rc1# cd src root@e3919192d9e3:/home/redis-3.0.0-rc1/src# mv redis-cli redis-server redis-sentinel /usr/bin/ root@e3919192d9e3:/home/redis-3.0.0-rc1/src# cd .. root@e3919192d9e3:/home/redis-3.0.0-rc1# mkdir -p /etc/redis/ root@e3919192d9e3:/home/redis-3.0.0-rc1# cp redis.conf /etc/redis/redis.conf
现在打开文件/etc/redis/redis.conf, 找到‘daemonize no’改为‘daemonize yes‘,然后启动它!
/etc/redis/redis.conf 在这个配置文件中我们只要找到‘salveof’这一行,然后去掉注释,修改为node1的ip地址,像下面这样: slaveof 172.17.0.2 6379
root@e3919192d9e3:/home/redis-3.0.0-rc1/src# redis-server /etc/redis/redis.conf root@e3919192d9e3:/home/redis-3.0.0-rc1/src#
好了, Redis现在已经安装好了,并且在容器里面运行了,使用的配置文件是/etc/redis/redis.conf。
3. 让Docker在启动容器的时候启动Redis服务
现在我们的容器正在运行Redis,并且也可以使用SSH登录了,我们还需要让它在容器启动的时候自动启动Redis服务,使用phusion基础镜像来实现这点相当的容易。首先,因为我们启动容器的时候使用了/sibn/my_init, 它会去运行任何我们放在/etc/service/*下面的程序。所以,对于我们来说,我们只要去创建一个目录以及在这个目录里面再创建一个叫run的文件,像下面这样:
vim redis.run
在这个run文件里面,我们加入下面的内容:
#!/bin/shset -e exec /usr/bin/redis-server /etc/redis/redis.conf
最后,记得给run文件添加可执行权限。
4. 提交镜像以便于重用
现在我们的redis容器运行良好, 我们想要把它保存为伪模板,以便在Docker上重复部署。做到这个非常简单,我们只要使用‘docker commit ...’这个镜像到我们本地的库就可以了,像下面这样:
现在把这个镜像推送到阿里云的镜像仓库里面
首页登录镜像仓库
docker login --username=zyf1985121 registry.cn-qingdao.aliyuncs.com
为镜像打个tag
docker tag eaa36147691f registry.cn-qingdao.aliyuncs.com/ylcaifu/docker:redis-cluster-node
提交镜像
docker push registry.cn-qingdao.aliyuncs.com/ylcaifu/docker:redis-cluster-node
查看
5. 部署新镜像的3个实例
为了解释清楚,我会删除之前创建的容器,以免后面搞晕。首先使用docker stop redis,之后再docker rm redis:
[root@svn zntg]# docker stop redis redis [root@svn zntg]# docker rm redis redis [root@svn zntg]#
很简单,下面让我们部署新镜像的3个实例,我们使用了Docker的端口映射机制,从而我们就可以使用Host服务器的IP访问这些实例,我们给这些实例关联的端口如下:
- node1 - hostip:7001
- node2 - hostip:7002
- node3 - hostip:7003
所以我们运行redis-cli -h 192.168.0.2 -p 7001,它将重定向到172.17.0.x -p 6379,例如下面我们部署了三个实例:
[root@svn zntg]# docker run -d --name node1 -p 7001:6379 redis-cluster-node /sbin/my_init 36ff5e40d09325599cdf2122a63065622ab36fea8ea2fb09621c83a966afbf2b [root@svn zntg]# docker run -d --name node2 -p 7002:6379 redis-cluster-node /sbin/my_init c0b3876f293ebe306de86b1b499d2614fe6228a2ba8cbb6fec5d730a2ef7ac45 [root@svn zntg]# docker run -d --name node3 -p 7003:6379 redis-cluster-node /sbin/my_init 73b1e766eb8081017a8d83d3aced043763ff61550a6bf368aa858234e4d0fe43 [root@svn zntg]#
现在我们可以运行docker ps -as来查看我们运行的三个Redis容器:
[root@svn zntg]# docker ps -as CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES SIZE 73b1e766eb80 redis-cluster-node "/sbin/my_init" 47 seconds ago Up 46 seconds 0.0.0.0:7003->6379/tcp node3 18.8 kB (virtual 456 MB) c0b3876f293e redis-cluster-node "/sbin/my_init" About a minute ago Up About a minute 0.0.0.0:7002->6379/tcp node2 18.8 kB (virtual 456 MB) 36ff5e40d093 redis-cluster-node "/sbin/my_init" About a minute ago Up About a minute 0.0.0.0:7001->6379/tcp node1 18.8 kB (virtual 456 MB) c1e4909a8f60 curiousby/centos-ssh-root-java-tomcat-maven-nexus-svn:original "/usr/local/nexus/..." 4 months ago Exited (255) 3 hours ago 0.0.0.0:3690->3690/tcp, 22/tcp, 0.0.0.0:8080-8081->8080-8081/tcp docker1 0 B [root@svn zntg]#
现在我们看到了3个容器,分别名字为node1、node2和node3,并且有一个专门的端口与Redis 服务的端口相映射。为了测试这样的映射是正确的,可以在另外一台机器使用redis-cli登录到各个Redis服务器上面:
root@36ff5e40d093:/home/redis-3.0.0-rc1/src# redis-cli -h 10.0.100.210 -p 7002 10.0.100.210:7002> quit root@36ff5e40d093:/home/redis-3.0.0-rc1/src# redis-cli -h 10.0.100.210 -p 7003 10.0.100.210:7003> quit root@36ff5e40d093:/home/redis-3.0.0-rc1/src# redis-cli -h 10.0.100.210 -p 7004 Could not connect to Redis at 10.0.100.210:7004: Connection refused not connected> quit root@36ff5e40d093:/home/redis-3.0.0-rc1/src# redis-cli -h 10.0.100.210 -p 7001 10.0.100.210:7001>
正如你看到的, 我们可以使用 hostip+port登录到对应的Redis服务器上, 当我们尝试一个不正确的端口时,却不行。
6. 配置Redis的从节点
我们有了三个独立的Redis服务器, 现在我们想把它们连接到一起, 从而我们可以测试这个集群的扩展性,对集群的监控,或者是做其它的事情。
我们把node1作为主节点,把node2和node3配置为它的从节点,这可以简单的通过修改/etc/redis/redis.conf这个文件来实现。SSH进入node2和node3节点,修改配置文件,然后重启容器:
进入node2容器里面
修改配置文件
/etc/redis/redis.conf 在这个配置文件中我们只要找到‘salveof’这一行,然后去掉注释,修改为node1的ip地址,像下面这样: slaveof 172.17.0.2 6379
node3执行同样的操作
最后使用命令docker restart node2重启容器, 现在它就是node1的一个从节点了。
为了验证这个, 使用redis-cli分别登录到node1和node2, 在node1上运行命令set hello world, 然后在node2上运行get hello,如果配置正确的话会得到下面的结果:
进入node1容器 docker exec -it node1 /bin/bash cd /home/redis-3.0.0-rc1/src# root@36ff5e40d093:/usr/bin# redis-cli -h 10.0.100.210 -p 7001
在node1容器里面设置一个key
set hello world
发现报错了
root@36ff5e40d093:/home/redis-3.0.0-rc1/src# redis-cli -h 10.0.100.210 -p 7001 10.0.100.210:7001> keys * Error: Connection reset by peer
解决这个错误是修改/etc/redis/redis.conf配置文件
将bind 127.0.0.1改为bind0.0.0.0
然后重启redis
root@36ff5e40d093:/usr/bin# redis-server /etc/redis/redis.conf
在执行命令
root@36ff5e40d093:/usr/bin# redis-cli -h 10.0.100.210 -p 7001 10.0.100.210:7001> set hello world OK 10.0.100.210:7001>
发现已经成功了,接下来我们在node2中取获取这个hello,看是否可以得到值
[root@svn sam]# docker exec -it node2 /bin/bash root@c0b3876f293e:/# vim etc/redis/redis.conf root@c0b3876f293e:/# cd /usr/bin/ root@c0b3876f293e:/usr/bin# redis-server /etc/redis/redis.conf root@c0b3876f293e:/usr/bin# redis-cli -h 10.0.100.210 -p 7002 10.0.100.210:7002> get hello "world" 10.0.100.210:7002>
正如我们期望的那样,在node2这个容器中,我们成功的拿到了node1里面设置的key的值
用reids客户端也可以成功连接
对于node3也做同样的配置即可。
[root@svn sam]# docker exec -it node3 /bin/bash root@73b1e766eb80:/# vim /etc/redis/redis.conf root@73b1e766eb80:/# cd /usr/bin/ root@73b1e766eb80:/usr/bin# redis-se redis-sentinel redis-server root@73b1e766eb80:/usr/bin# redis-server /et/redis/redis.conf 1655:C 22 Jul 14:32:15.043 # Fatal error, can't open config file '/et/redis/redis.conf' root@73b1e766eb80:/usr/bin# redis-server /etc/redis/redis.conf root@73b1e766eb80:/usr/bin# redis-cli -h 10.0.100.210 -p 7003 10.0.100.210:7003> get hello "world" 10.0.100.210:7003>
恭喜,基于Docker的、拥有三个节点且可水平扩展的Redis集群就这样搭好了。
接下来的下一篇博客中,我将给大家展示如何使用Opsview去监控Redis集群,你可以看到一个像下面这样展示你的集群统计信息的可视化界面:
相关推荐
用Docker构建分布式Redis集群 【编者的话】本文介绍了如何使用Docker搭建Redis集群,很多读者都在问Docker能带来哪些实质性的好处,我想本文就是一个很好的例子。不使用Docker你也可以搭建Redis集群,那使用Docker后...
第2章 RR开源前后端分离项目下载与配置,第4章 搭建MySQL集群,第5章 搭建Redis集群
"docker 实现redis集群搭建" 一、Redis Cluster 概念 Redis Cluster 是 Redis 的分布式解决方案,旨在解决 Redis 单机中心化的问题。它将整个数据集按照分区规则映射到多个节点上,使得 Redis 能够水平扩展以应对...
Redis集群是Redis提供的分布式数据库方案,集群通过分片(sharding)来进行数据共享,并提供复制和故障转移功能。 节点 一个Redis集群通常由多个节点(node)组成,在刚开始的时候,每个节点都是相互独立的,它们都...
redis是一款分布式缓存服务,对于大型的系统开发以及性能优化缓存也是必不可少的一种手段,这时候redis就因此而生,由于redis是将数据缓存到内存条中的,所以它的读取速度和写入速度都是很快的,传统的像关系型...
总的来说,"redis集群 三主三从模式"提供了一种健壮的分布式数据库解决方案,利用Docker和docker-compose简化了部署流程。熟悉并掌握这种配置方法,对于保障高可用性和数据安全性至关重要。在实际应用中,还应考虑...
综合以上,这个项目利用Spring Boot的便利性构建了一个能够驱动Docker容器进行数据计算、通过Redis管理任务队列以及借助BBoss和Elasticsearch客户端进行日志记录的系统。这样的架构具有高度的灵活性和可扩展性,便于...
在本文中,我们将深入探讨如何基于Docker搭建一个Redis集群,包括一主两从和三个哨兵节点。这种配置能够提供高可用性和数据复制,确保即使在主节点故障时,服务也能正常运行。 首先,我们需要了解Docker。Docker是...
【标题】:Docker Redis ...总结,Docker Compose与Redis Cluster的结合,为开发者提供了一种便捷、灵活的方式来部署和管理分布式Redis环境。理解并熟练掌握Redis的配置和集群管理,对于提升系统性能和稳定性至关重要。
**Redis集群介绍** ...通过理解Redis集群的工作原理和Docker的使用,我们可以高效地构建和管理高可用的Redis服务。而`redis-cluster-docker-develop`文件则可能是实现这一过程的具体代码或配置文件。
1、支持单实例 ...3、支持多机分布式集群部署 4、支持redis哨兵集群数据、日志、配置文件持久化 5、支持数据目录、日志目录、端口、密码参数灵活配置 6、支持创建、启动、停止、检测、卸载redis哨兵集群
这个“Redis-Swarm分布式集群部署脚本”旨在帮助用户快速、便捷地在多台服务器上构建一个高可用的Redis集群。 首先,了解Redis-Swarm的基础概念: 1. Redis:Redis是一个高性能的键值存储系统,常用于缓存、消息...
SpringCloud 是一套完整的微服务解决方案,它为开发者提供了构建分布式系统所需的工具,包括服务发现、配置管理、断路器、智能路由、微代理、控制总线、一次性令牌、全局锁、领导选举、分布式会话、集群状态等。...
docker集群部署redis,zk,kafka
一键部署工具实现功能如下: 1、支持伪集群部署 2、支持分布式集群部署 3、支持redis cluster集群数据、日志、配置文件...说明:工具使用非常简单,只需要修改变量文件,一分钟就可以快速帮你部署redis cluster集群。
一键部署工具实现功能如下: 1、支持伪集群部署 2、支持分布式集群部署 3、支持redis哨兵集群数据、日志、配置文件持久化 ...说明:工具使用非常简单,只需要修改变量文件,一分钟就可以快速帮你部署redis哨兵集群。
在构建大型的电商平台时,分布式集群技术是不可或缺的组成部分。它能够提高系统的可扩展性、容错性和性能,确保在高并发访问下也能稳定运行。本方案将详细介绍如何使用Java实现一个分布式集群电商平台。 一、分布式...