Docker 搭建 Redis Cluster 集群环境

{"type":"doc","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"使用 Docker 搭建 Redis Cluster,最重要的环节就是容器通信的问题,这一块我们在之前的文章中已经给大家解决了《"},{"type":"link","attrs":{"href":"https://xie.infoq.cn/article/97355a6e7ac01bce8532d5ff5","title":""},"content":[{"type":"text","text":"Docker网络模式详解及容器间网络通信"}]},{"type":"text","text":"》,本篇文章主要练习使用多个容器完成 Redis Cluster 集群环境的搭建,顺便为学习 Docker Compose 铺铺路。俗话说没有对比就没有伤害,通过对比才能感受到 Docker Compose 的好处 😄。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  关于 Redis Cluster 集群更多的内容请阅读《"},{"type":"link","attrs":{"href":"https://xie.infoq.cn/article/fe070dcadf891d3d641132c36","title":""},"content":[{"type":"text","text":"最通俗易懂的 Redis 架构模式详解"}]},{"type":"text","text":"》。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"环境"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  本文所使用的基础设施环境如下:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"CentOS 7.8.2003"}]}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"Docker version 19.03.12 "}]}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/03/0309ecfc01393c56c1e87247cc673c77.png","alt":null,"title":" ","style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"搭建"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  整体搭建步骤主要分为以下几步:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"创建网络;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"下载 Redis 镜像(其实这步可以省略,因为创建容器时,如果本地镜像不存在,就会去远程拉取);"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"编写 Redis 配置文件;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"创建 Redis 容器;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"创建 Redis Cluster 集群。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"创建网络"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  为什么需要创建网络?因为:默认的 bridge 网络是无法使用 DNS 的,所以我们就需要自定义网络。说简单点就是为了让容器可以直接通过容器名称进行通信。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  从 Docker 1.10 版本开始,docker daemon 实现了一个内嵌的 DNS server,使容器可以直接通过容器名称进行通信。方法很简单,只要在创建容器时使用 "},{"type":"codeinline","content":[{"type":"text","text":"--name"}]},{"type":"text","text":" 为容器命名即可。"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":">"}]},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  但是使用 Docker DNS 有个限制:"},{"type":"text","marks":[{"type":"strong"}],"text":"只能在 user-defined 网络中使用"},{"type":"text","text":"。也就是说,默认的 bridge 网络是无法使用 DNS 的,所以我们就需要自定义网络。"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  通过 "},{"type":"codeinline","content":[{"type":"text","text":"docker network create"}]},{"type":"text","text":" 命令可以创建自定义网络模式,默认为 "},{"type":"codeinline","content":[{"type":"text","text":"bridge"}]},{"type":"text","text":" 网桥/桥接模式,完整命令如下:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"shell"},"content":[{"type":"text","text":"docker network create redis-net"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  通过 "},{"type":"codeinline","content":[{"type":"text","text":"docker network ls"}]},{"type":"text","text":" 查看网络模式:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/00/0086d870d9540478cf1421714e28e943.png","alt":null,"title":" ","style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  我们还可以通过 "},{"type":"codeinline","content":[{"type":"text","text":"docker network inspect redis-net"}]},{"type":"text","text":" 查看 "},{"type":"codeinline","content":[{"type":"text","text":"redis-net"}]},{"type":"text","text":" 网络的详细信息:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/86/864cc532a8fa020da84fc38297a4c623.png","alt":null,"title":" ","style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"编写 Redis 配置文件"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"创建目录及文件"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"shell"},"content":[{"type":"text","text":"# 创建目录\nmkdir -p /usr/local/docker-redis/redis-cluster\n# 切换至指定目录\ncd /usr/local/docker-redis/redis-cluster/\n# 编写 redis-cluster.tmpl 文件\nvi redis-cluster.tmpl"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"编写配置文件"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  "},{"type":"codeinline","content":[{"type":"text","text":"redis-cluster.tmpl"}]},{"type":"text","text":" 文件内容如下:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"tepl"},"content":[{"type":"text","text":"port ${PORT}\nrequirepass 1234\nmasterauth 1234\nprotected-mode no\ndaemonize no\nappendonly yes\ncluster-enabled yes\ncluster-config-file nodes.conf\ncluster-node-timeout 15000\ncluster-announce-ip 192.168.10.10\ncluster-announce-port ${PORT}\ncluster-announce-bus-port 1${PORT}"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"port"}]},{"type":"text","text":":节点端口;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"requirepass"}]},{"type":"text","text":":添加访问认证;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"masterauth"}]},{"type":"text","text":":如果主节点开启了访问认证,从节点访问主节点需要认证;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"protected-mode"}]},{"type":"text","text":":保护模式,默认值 yes,即开启。开启保护模式以后,需配置 "},{"type":"codeinline","content":[{"type":"text","text":"bind ip"}]},{"type":"text","text":" 或者设置访问密码;关闭保护模式,外部网络可以直接访问;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"daemonize"}]},{"type":"text","text":":是否以守护线程的方式启动(后台启动),默认 no;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"appendonly"}]},{"type":"text","text":":是否开启 AOF 持久化模式,默认 no;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"cluster-enabled"}]},{"type":"text","text":":是否开启集群模式,默认 no;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"cluster-config-file"}]},{"type":"text","text":":集群节点信息文件;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"cluster-node-timeout"}]},{"type":"text","text":":集群节点连接超时时间;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"cluster-announce-ip"}]},{"type":"text","text":":集群节点 IP,这里需要特别注意一下,如果要对外提供访问功能,需要填写宿主机的 IP,如果填写 Docker 分配的 IP(172.x.x.x),可能会导致外部无法正常访问集群;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"cluster-announce-port"}]},{"type":"text","text":":集群节点映射端口;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"cluster-announce-bus-port"}]},{"type":"text","text":":集群节点总线端口。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  每个 Redis 集群节点都需要打开"},{"type":"text","marks":[{"type":"strong"}],"text":"两个 TCP 连接"},{"type":"text","text":"。一个用于为客户端提供服务的正常 Redis TCP 端口,例如 6379。还有一个基于 6379 端口加 10000 的端口,比如 16379。"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":">"}]},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  第二个端口用于集群总线,这是一个使用二进制协议的节点到节点通信通道。节点使用集群总线进行故障检测、配置更新、故障转移授权等等。客户端永远不要尝试与集群总线端口通信,与正常的 Redis 命令端口通信即可,但是请确保防火墙中的这两个端口都已经打开,否则 Redis 集群节点将无法通信。"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  在 "},{"type":"codeinline","content":[{"type":"text","text":"redis-cluster"}]},{"type":"text","text":" 目录下执行以下命令:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"shell"},"content":[{"type":"text","text":"for port in `seq 6371 6376`; do \\\n mkdir -p ${port}/conf \\\n && PORT=${port} envsubst < redis-cluster.tmpl > ${port}/conf/redis.conf \\\n && mkdir -p ${port}/data;\\\ndone"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"上面是一段 shell for 语句,意思就是循环创建 6371 ~ 6376 相关的目录及文件。"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  查看命令执行结果,如果没有 "},{"type":"codeinline","content":[{"type":"text","text":"tree"}]},{"type":"text","text":" 命令先安装 "},{"type":"codeinline","content":[{"type":"text","text":"yum install -y tree"}]},{"type":"text","text":"。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/97/978a3123c8900202d23454c01c181c78.png","alt":null,"title":" ","style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  以下内容为每个节点的配置文件详细信息。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"shell"},"content":[{"type":"text","text":"[root@localhost redis-cluster]# cat /usr/local/docker-redis/redis-cluster/637{1..6}/conf/redis.conf\nport 6371\nrequirepass 1234\nmasterauth 1234\nprotected-mode no\ndaemonize no\nappendonly yes\ncluster-enabled yes\ncluster-config-file nodes.conf\ncluster-node-timeout 15000\ncluster-announce-ip 192.168.10.10\ncluster-announce-port 6371\ncluster-announce-bus-port 16371\n\nport 6372\nrequirepass 1234\nmasterauth 1234\nprotected-mode no\ndaemonize no\nappendonly yes\ncluster-enabled yes\ncluster-config-file nodes.conf\ncluster-node-timeout 15000\ncluster-announce-ip 192.168.10.10\ncluster-announce-port 6372\ncluster-announce-bus-port 16372\n\nport 6373\nrequirepass 1234\nmasterauth 1234\nprotected-mode no\ndaemonize no\nappendonly yes\ncluster-enabled yes\ncluster-config-file nodes.conf\ncluster-node-timeout 15000\ncluster-announce-ip 192.168.10.10\ncluster-announce-port 6373\ncluster-announce-bus-port 16373\n\nport 6374\nrequirepass 1234\nmasterauth 1234\nprotected-mode no\ndaemonize no\nappendonly yes\ncluster-enabled yes\ncluster-config-file nodes.conf\ncluster-node-timeout 15000\ncluster-announce-ip 192.168.10.10\ncluster-announce-port 6374\ncluster-announce-bus-port 16374\n\nport 6375\nrequirepass 1234\nmasterauth 1234\nprotected-mode no\ndaemonize no\nappendonly yes\ncluster-enabled yes\ncluster-config-file nodes.conf\ncluster-node-timeout 15000\ncluster-announce-ip 192.168.10.10\ncluster-announce-port 6375\ncluster-announce-bus-port 16375\n\nport 6376\nrequirepass 1234\nmasterauth 1234\nprotected-mode no\ndaemonize no\nappendonly yes\ncluster-enabled yes\ncluster-config-file nodes.conf\ncluster-node-timeout 15000\ncluster-announce-ip 192.168.10.10\ncluster-announce-port 6376\ncluster-announce-bus-port 16376"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"创建 Redis 容器"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"创建容器"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  将宿主机的 "},{"type":"codeinline","content":[{"type":"text","text":"6371 ~ 6376"}]},{"type":"text","text":" 之间的端口与 6 个 Redis 容器映射,并将宿主机的目录与容器内的目录进行映射(目录挂载)。记得指定网络模式,使用我们自己创建的 "},{"type":"codeinline","content":[{"type":"text","text":"redis-net"}]},{"type":"text","text":" 网络。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"shell"},"content":[{"type":"text","text":"for port in $(seq 6371 6376); do \\\n docker run -di -p ${port}:${port} -p 1${port}:1${port} \\\n --restart always --name redis-${port} --net redis-net \\\n -v /usr/local/docker-redis/redis-cluster/${port}/conf/redis.conf:/usr/local/etc/redis/redis.conf \\\n -v /usr/local/docker-redis/redis-cluster/${port}/data:/data \\\n redis redis-server /usr/local/etc/redis/redis.conf; \\\ndone"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  "},{"type":"codeinline","content":[{"type":"text","text":"docker ps -n 6"}]},{"type":"text","text":" 查看容器是否创建成功。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/65/65c7a2d40776880113619b35f4aa88ca.png","alt":null,"title":" ","style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  "},{"type":"codeinline","content":[{"type":"text","text":"docker network inspect redis-net | grep -i -E \"name|ipv4address\""}]},{"type":"text","text":" 查看给每个节点分配的IP信息。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/56/569552c67696cbb8aab1fcf2a8314b7d.png","alt":null,"title":" ","style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"创建 Redis Cluster 集群"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  随便进入一个容器节点,并进入 "},{"type":"codeinline","content":[{"type":"text","text":"/usr/local/bin/"}]},{"type":"text","text":" 目录:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"shell"},"content":[{"type":"text","text":"# 进入容器\ndocker exec -it redis-6371 bash\n# 切换至指定目录\ncd /usr/local/bin/"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  接下来我们就可以通过以下命令实现 Redis Cluster 集群的创建。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"shell"},"content":[{"type":"text","text":"redis-cli -a 1234 --cluster create 172.18.0.2:6371 172.18.0.3:6372 172.18.0.4:6373 172.18.0.5:6374 172.18.0.6:6375 172.18.0.7:6376 --cluster-replicas 1"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  出现选择提示信息,输入 "},{"type":"text","marks":[{"type":"strong"}],"text":"yes"},{"type":"text","text":",结果如下所示:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/84/844c6920f8100e01b1b0538f4edf27e0.png","alt":null,"title":" ","style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  集群创建成功如下:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/ce/cee8c8f5666ea3ca91706d46a48a04cd.png","alt":null,"title":" ","style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  以下内容是创建集群时返回的详细信息,也就是上两幅图中的所有内容。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"shell"},"content":[{"type":"text","text":"root@705a5ec95a2e:/usr/local/bin# redis-cli -a 1234 --cluster create 172.18.0.2:6371 172.18.0.3:6372 172.18.0.4:6373 172.18.0.5:6374 172.18.0.6:6375 172.18.0.7:6376 --cluster-replicas 1\nWarning: Using a password with '-a' or '-u' option on the command line interface may not be safe.\n>>> Performing hash slots allocation on 6 nodes...\nMaster[0] -> Slots 0 - 5460\nMaster[1] -> Slots 5461 - 10922\nMaster[2] -> Slots 10923 - 16383\nAdding replica 172.18.0.6:6375 to 172.18.0.2:6371\nAdding replica 172.18.0.7:6376 to 172.18.0.3:6372\nAdding replica 172.18.0.5:6374 to 172.18.0.4:6373\nM: 4dbede8f79c98a8cf63556387ce8c2a793d20089 172.18.0.2:6371\n slots:[0-5460] (5461 slots) master\nM: c2117d59666f20be5a29485b2e22753991a2dcb9 172.18.0.3:6372\n slots:[5461-10922] (5462 slots) master\nM: a5a8fdda426785c54a0e557b753ef571d22581a7 172.18.0.4:6373\n slots:[10923-16383] (5461 slots) master\nS: 4aca662dbc0d40498592c11c8dcb94b62c39b15c 172.18.0.5:6374\n replicates a5a8fdda426785c54a0e557b753ef571d22581a7\nS: 55fe2da8fe4fb1acdf950a6030a6304713eb613b 172.18.0.6:6375\n replicates 4dbede8f79c98a8cf63556387ce8c2a793d20089\nS: be84c1e8600986d5ebfbd2e18611dc4d1ace41a7 172.18.0.7:6376\n replicates c2117d59666f20be5a29485b2e22753991a2dcb9\nCan I set the above configuration? (type 'yes' to accept): yes\n>>> Nodes configuration updated\n>>> Assign a different config epoch to each node\n>>> Sending CLUSTER MEET messages to join the cluster\nWaiting for the cluster to join\n\n>>> Performing Cluster Check (using node 172.18.0.2:6371)\nM: 4dbede8f79c98a8cf63556387ce8c2a793d20089 172.18.0.2:6371\n slots:[0-5460] (5461 slots) master\n 1 additional replica(s)\nS: be84c1e8600986d5ebfbd2e18611dc4d1ace41a7 192.168.10.10:6376\n slots: (0 slots) slave\n replicates c2117d59666f20be5a29485b2e22753991a2dcb9\nM: c2117d59666f20be5a29485b2e22753991a2dcb9 192.168.10.10:6372\n slots:[5461-10922] (5462 slots) master\n 1 additional replica(s)\nM: a5a8fdda426785c54a0e557b753ef571d22581a7 192.168.10.10:6373\n slots:[10923-16383] (5461 slots) master\n 1 additional replica(s)\nS: 4aca662dbc0d40498592c11c8dcb94b62c39b15c 192.168.10.10:6374\n slots: (0 slots) slave\n replicates a5a8fdda426785c54a0e557b753ef571d22581a7\nS: 55fe2da8fe4fb1acdf950a6030a6304713eb613b 192.168.10.10:6375\n slots: (0 slots) slave\n replicates 4dbede8f79c98a8cf63556387ce8c2a793d20089\n[OK] All nodes agree about slots configuration.\n>>> Check for open slots...\n>>> Check slots coverage...\n[OK] All 16384 slots covered."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  至此一个高可用的 Redis Cluster 集群搭建完成,如下图所示,该集群中包含 6 个 Redis 节点,3 主 3 从。三个主节点会分配槽,处理客户端的命令请求,而从节点可用在主节点故障后,顶替主节点。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/27/27ad2d63da3a5939ff37f79c0baa3f49.png","alt":null,"title":" ","style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"查看集群状态"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  我们先进入容器,然后通过一些集群常用的命令查看一下集群的状态。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"shell"},"content":[{"type":"text","text":"# 进入容器\ndocker exec -it redis-6371 bash\n# 切换至指定目录\ncd /usr/local/bin/"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"检查集群状态"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  因为我们使用了自定义的网络进行容器管理,这样可以使容器直接通过容器名称通信。推荐使用这种方式。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"shell"},"content":[{"type":"text","text":"# 使用 IP\nredis-cli -a 1234 --cluster check 192.168.10.10:6371\n# 使用容器名称\nredis-cli -a 1234 --cluster check redis-6372:6372"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/94/94c31410b6a03bebd377a937321f28ef.png","alt":null,"title":" ","style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"查看集群信息和节点信息"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"shell"},"content":[{"type":"text","text":"# 连接至集群某个节点\nredis-cli -c -a 1234 -h redis-6373 -p 6373\n# 查看集群信息\ncluster info\n# 查看集群结点信息\ncluster nodes"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/19/19fcfd1a639370243688dc338657b224.png","alt":null,"title":" ","style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"SET/GET"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  在 6371 节点中执行写入和读取,命令如下:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"shell"},"content":[{"type":"text","text":"# 进入容器并连接至集群某个节点\ndocker exec -it redis-6371 /usr/local/bin/redis-cli -c -a 1234 -h redis-6371 -p 6371\n# 写入数据\nset name mrhelloworld\nset aaa 111\nset bbb 222\n# 读取数据\nget name\nget aaa\nget bbb"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/5e/5e9bc4e5e6a918637c6a0bcc2cb34fac.png","alt":null,"title":" ","style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  别着急,让我来解释一下上图中的操作过程:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"首先进入容器并连接至集群某个节点;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"然后执行"},{"type":"text","marks":[{"type":"strong"}],"text":"第一个"},{"type":"text","text":" set 命令 "},{"type":"codeinline","content":[{"type":"text","text":"set name mrhelloworld"}]},{"type":"text","text":","},{"type":"codeinline","content":[{"type":"text","text":"name"}]},{"type":"text","text":" 键根据哈希函数运算以后得到的值为 "},{"type":"codeinline","content":[{"type":"text","text":"[5798]"}]},{"type":"text","text":"。当前集群环境的槽分配情况为:"},{"type":"codeinline","content":[{"type":"text","text":"[0-5460] 6371节点"}]},{"type":"text","text":","},{"type":"codeinline","content":[{"type":"text","text":"[5461-10922] 6372节点"}]},{"type":"text","text":","},{"type":"codeinline","content":[{"type":"text","text":"[10923-16383] 6373节点"}]},{"type":"text","text":",所以该键的存储就被分配到了 "},{"type":"text","marks":[{"type":"strong"}],"text":"6372"},{"type":"text","text":" 节点上;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"再来看"},{"type":"text","marks":[{"type":"strong"}],"text":"第二个"},{"type":"text","text":" set 命令 "},{"type":"codeinline","content":[{"type":"text","text":"set aaa"}]},{"type":"text","text":",这里大家可能会有一些疑问,为什么看不到 "},{"type":"codeinline","content":[{"type":"text","text":"aaa"}]},{"type":"text","text":" 键根据哈希函数运算以后得到的值?因为刚才重定向至 "},{"type":"text","marks":[{"type":"strong"}],"text":"6372"},{"type":"text","text":" 节点插入了数据,此时如果还有数据插入,正好键根据哈希函数运算以后得到的值也还在该节点的范围内,那么直接插入数据即可;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"接着是"},{"type":"text","marks":[{"type":"strong"}],"text":"第三个"},{"type":"text","text":" set 命令 "},{"type":"codeinline","content":[{"type":"text","text":"set bbb"}]},{"type":"text","text":","},{"type":"codeinline","content":[{"type":"text","text":"bbb"}]},{"type":"text","text":" 键根据哈希函数运算以后得到的值为 "},{"type":"codeinline","content":[{"type":"text","text":"[5287]"}]},{"type":"text","text":",所以该键的存储就被分配到了 "},{"type":"text","marks":[{"type":"strong"}],"text":"6371"},{"type":"text","text":" 节点上;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"然后是读取操作,"},{"type":"text","marks":[{"type":"strong"}],"text":"第四个"},{"type":"text","text":"命令 "},{"type":"codeinline","content":[{"type":"text","text":"get name"}]},{"type":"text","text":","},{"type":"codeinline","content":[{"type":"text","text":"name"}]},{"type":"text","text":" 键根据哈希函数运算以后得到的值为 "},{"type":"codeinline","content":[{"type":"text","text":"[5798]"}]},{"type":"text","text":",被重定向至 "},{"type":"text","marks":[{"type":"strong"}],"text":"6372"},{"type":"text","text":" 节点读取;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"第五个"},{"type":"text","text":"命令 "},{"type":"codeinline","content":[{"type":"text","text":"get aaa"}]},{"type":"text","text":","},{"type":"codeinline","content":[{"type":"text","text":"aaa"}]},{"type":"text","text":" 键根据哈希函数运算以后得到的值也在 "},{"type":"text","marks":[{"type":"strong"}],"text":"6372"},{"type":"text","text":" 节点,直接读取;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"第六个"},{"type":"text","text":"命令 "},{"type":"codeinline","content":[{"type":"text","text":"get bbb"}]},{"type":"text","text":","},{"type":"codeinline","content":[{"type":"text","text":"bbb"}]},{"type":"text","text":" 键根据哈希函数运算以后得到的值为 "},{"type":"codeinline","content":[{"type":"text","text":"[5287]"}]},{"type":"text","text":",被重定向至 "},{"type":"text","marks":[{"type":"strong"}],"text":"6371"},{"type":"text","text":" 节点读取。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  通过以上操作我们得知 "},{"type":"codeinline","content":[{"type":"text","text":"name"}]},{"type":"text","text":" 键的存储被分配到了 6372 节点,如果直接连接 6372 节点并获取该值会怎么样?没错,不需要重定向节点,因为数据就在该节点,所以直接读取返回。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/22/22a8ef10b1895ab2874883a67b4e35b8.png","alt":null,"title":" ","style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  总结下来就是,在 "},{"type":"text","marks":[{"type":"strong"}],"text":"Redis Cluster 集群模式"},{"type":"text","text":"中,*"},{"type":"text","marks":[{"type":"italic"}],"text":"无论连接哪个节点"},{"type":"text","text":"*,每次我们"},{"type":"text","marks":[{"type":"strong"}],"text":"执行写入或者读取"},{"type":"text","text":"操作的时候,所有的"},{"type":"text","marks":[{"type":"strong"}],"text":"键会根据哈希函数运算并映射到 0 ~ 16383 整数槽内"},{"type":"text","text":",如果恰好对应的"},{"type":"text","marks":[{"type":"strong"}],"text":"槽"},{"type":"text","text":"就在你"},{"type":"text","marks":[{"type":"strong"}],"text":"当前连接的节点"},{"type":"text","text":"中,则"},{"type":"text","marks":[{"type":"strong"}],"text":"直接执行"},{"type":"text","text":"命令,"},{"type":"text","marks":[{"type":"strong"}],"text":"否则重定向"},{"type":"text","text":"至对应节点执行命令。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"客户端连接"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  最后来一波客户端连接操作,随便哪个节点,看看可否通过外部访问 Redis Cluster 集群。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/c9/c92b7339c9633ff015f1ccd8198843a3.png","alt":null,"title":" ","style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/67/67e313bd75548e98ee916599936b5b98.png","alt":null,"title":" ","style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  至此使用多个容器搭建 Redis Cluster 集群环境就到这里,其实整体搭建过程不算特别麻烦,因为:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"创建 Redis 集群需要用到 Ruby,否则就得自己关联节点构建集群,自己分配槽;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果使用 Ruby 构建 Redis 集群,就需要安装 Ruby 环境;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"而 Redis 从 5 版本开始可以直接使用 "},{"type":"codeinline","content":[{"type":"text","text":"redis-cli"}]},{"type":"text","text":" 命令创建集群了,就省去了很多麻烦事;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我们还使用了 shell for 循环语句简化了构建过程,否则那些语句一条条执行也够你闹心的。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  综上所述,有没有更简单的办法呢?当然有了,不然我在这跟你卖什么关子。"}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/ca/ca6a0cd443ac48cb6049c0c13278eec1.jpeg","alt":null,"title":"","style":[{"key":"width","value":"25%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"  Docker Compose 就可以解决这个问题。后面我们先学习一下什么是 Docker Compose,然后使用 Docker Compose 再来搭建一遍 Redis Cluster 集群环境,感受感受这前后的区别。"}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/3f/3f2b7927a66dc6426ff7a6f46f8d35a3.gif","alt":null,"title":"","style":[{"key":"width","value":"50%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"本文采用 "},{"type":"link","attrs":{"href":"http://creativecommons.org/licenses/by-nc-nd/4.0/","title":null},"content":[{"type":"text","text":"知识共享「署名-非商业性使用-禁止演绎 4.0 国际」许可协议"}]},{"type":"text","text":"。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"大家可以通过 "},{"type":"link","attrs":{"href":"https://mrhelloworld.com/categories/docker","title":null},"content":[{"type":"text","text":"分类"}]},{"type":"text","text":" 查看更多关于 "},{"type":"link","attrs":{"href":"https://mrhelloworld.com/categories/docker","title":null},"content":[{"type":"text","text":"Docker"}]},{"type":"text","text":" 的文章。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":""}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"🤗 您的"},{"type":"codeinline","content":[{"type":"text","text":"点赞"}]},{"type":"text","text":"和"},{"type":"codeinline","content":[{"type":"text","text":"转发"}]},{"type":"text","text":"是对我最大的支持。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"📢 扫码关注 "},{"type":"codeinline","content":[{"type":"text","text":"哈喽沃德先生"}]},{"type":"text","text":"「文档 + 视频」每篇文章都配有专门视频讲解,学习更轻松噢 ~"}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/67/6739b2ed350171f1bca3a0238715c45f.gif","alt":null,"title":"","style":[{"key":"width","value":"50%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/1c/1c2456f4fc38ffa2fd1e6c975127550b.jpeg","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章