# 部署Redis集群

两种方式安装Redis

## 使用Docker Compose部署基于Sentinel的高可用Redis集群

本文将介绍如何利用Docker Compose模板在本机和云端部署基于Sentinel的高可用Redis 3集群。

Redis集群可以在一组redis节点之间实现高可用性和sharding。今天我们重点围绕master-slave的高可用模式来进行讨论，在集群中会有1个master和多个slave节点。当master节点失效时，应选举出一个slave节点作为新的master。然而Redis本身(包括它的很多客户端)没有实现自动故障发现并进行主备切换的能力，需要外部的监控方案来实现自动故障恢复。

Redis Sentinel是官方推荐的高可用性解决方案。它是Redis集群的监控管理工具，可以提供节点监控、通知、自动故障恢复和客户端配置发现服务。

今天我们的部署模型是 [Redis Sentinel](https://yq.aliyun.com/go/articleRenderRedirect?url=http://redis.io/topics/sentinel) 介绍的实例二，也是实战中比较常见的一种部署模式：

![14692659415657](http://img1.tbcdn.cn/L1/461/1/18841d5327556bfa750148943011901d1eac3cd8)

本文所有示例代码都可以从 [https://github.com/AliyunContainerService/redis-cluster](https://yq.aliyun.com/go/articleRenderRedirect?url=https://github.com/AliyunContainerService/redis-cluster) 获得

本文采用的Redis镜像全部基于Docker提供的[Redis官方镜像3.2.1](https://yq.aliyun.com/go/articleRenderRedirect?url=https://hub.docker.com/_/redis/)

#### 单机部署Redis集群 <a href="#id-1" id="id-1"></a>

下面的测试需要本地环境已经安装Docker Engine和Docker Compose，推荐使用Docker for Mac/Windows。想在云端部署的同学可以直接跳到下一节

下载代码

```
git clone https://github.com/AliyunContainerService/redis-cluster
cd redis-cluster
```

目录下面的`docker-compose.yml`模板定义Redis集群的服务组成

```
master:
  image: redis:3
slave:
  image: redis:3
  command: redis-server --slaveof redis-master 6379
  links:
    - master:redis-master
sentinel:
  build: sentinel
  environment:
    - SENTINEL_DOWN_AFTER=5000
    - SENTINEL_FAILOVER=5000    
  links:
    - master:redis-master
    - slave
```

在模板中定义了下面一系列服务

* master: Redis master
* slave: Redis slave
* sentinel: Redis Sentinel

其中sentinel服务的Docker镜像是由 "./sentinel" 目录中的Dockerfile构建完成，只是在官方Redis镜像上添加了`sentinel.conf`配置文件，并以sentinel模式启动容器。其配置文件如下，其中包含了sentinel对名为"mymaster"的集群的监控配置：

```
sentinel monitor mymaster redis-master 6379 2
sentinel down-after-milliseconds mymaster 5000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 5000
```

细节请参见`sentinel.conf`配置自身。

**注意：**

* slave和sentinel容器初始化配置的Redis master节点主机名为"redis-master"，这里我们利用了Docker容器连接的别名机制来连接master和sentinel/slave容器实例
* 由于我们会部署3个Sentinel，我们把sentinel的"quorum"设置为2，只有两个sentinel同意故障切换，才会真正切换相应的redis master节点。

下面我们先构建 sentinel 服务所需 Docker image

```
docker-compose build
```

一键部署并启动Redis集群

```
docker-compose up -d
```

这时我们可以检查集群状态，应该是包含3个容器，1个master, 1个slave，和1个sentinel

```
docker-compose ps
```

显示结果如下

```
         Name                        Command               State          Ports        
--------------------------------------------------------------------------------------
rediscluster_master_1     docker-entrypoint.sh redis ...   Up      6379/tcp            
rediscluster_sentinel_1   docker-entrypoint.sh redis ...   Up      26379/tcp, 6379/tcp 
rediscluster_slave_1      docker-entrypoint.sh redis ...   Up      6379/tcp     
```

我们可以伸缩sentinel的实例数量到3个

```
docker-compose scale sentinel=3
```

伸缩slave的实例数量到2个，这样我们就有3个redis实例了（包含一个master)

```
docker-compose scale slave=2
```

检查集群状态，结果如下

```
docker-compose ps

         Name                        Command               State          Ports        
--------------------------------------------------------------------------------------
rediscluster_master_1     docker-entrypoint.sh redis ...   Up      6379/tcp            
rediscluster_sentinel_1   docker-entrypoint.sh redis ...   Up      26379/tcp, 6379/tcp 
rediscluster_sentinel_2   docker-entrypoint.sh redis ...   Up      26379/tcp, 6379/tcp 
rediscluster_sentinel_3   docker-entrypoint.sh redis ...   Up      26379/tcp, 6379/tcp 
rediscluster_slave_1      docker-entrypoint.sh redis ...   Up      6379/tcp            
rediscluster_slave_2      docker-entrypoint.sh redis ...   Up      6379/tcp            
```

我们可以利用下面的测试脚本来模拟master节点失效，并验证Redis集群的自动主从切换。

```
./test.sh
```

这个测试脚本实际上利用 `docker pause` 命令将 Redis master容器暂停，sentinel会发现这个故障并将master切换到其他一个备用的slave上面。

执行结果如下

```
Redis master: 172.17.0.2
Redis Slave: 172.17.0.3
------------------------------------------------
Initial status of sentinel
------------------------------------------------
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=172.17.0.2:6379,slaves=2,sentinels=3
Current master is
172.17.0.2
6379
------------------------------------------------
Stop redis master
rediscluster_master_1
Wait for 10 seconds
Current infomation of sentinel
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=172.17.0.3:6379,slaves=2,sentinels=3
Current master is
172.17.0.3
6379
------------------------------------------------
Restart Redis master
rediscluster_master_1
Current infomation of sentinel
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=172.17.0.3:6379,slaves=2,sentinels=3
Current master is
172.17.0.3
6379
```

我们可以利用Docker Compose方便地在本地验证Redis集群的部署和故障恢复，但是这还不是一个分布式的高可用部署。我们下面会利用阿里云容器服务来进行验证

#### 云端部署高可用Redis集群 <a href="#id-2" id="id-2"></a>

[阿里云容器服务](https://yq.aliyun.com/go/articleRenderRedirect?url=https://www.aliyun.com/product/containerservice) 在兼容Docker Compose编排模板的基础上，做了大量的扩展。能够更好地帮助我们在Docker集群中部署分布式应用。

首先您需要创建一个包含至少三个节点的集群（否则您需要注释掉相应的"affinity:service"部署约束）

然后我们利用下面的 docker compose模板部署高可用Redis集群

```
master:
  image: redis:3
  environment:
    - affinity:service!=slave
  restart: always
slave:
  image: redis:3
  command: redis-server --slaveof redis-master 6379
  environment:
    - affinity:service!=master
    - affinity:service!=slave
  labels: 
    aliyun.scale: "2"
  restart: always
  links:
    - master:redis-master
sentinel:
  image: registry.aliyuncs.com/acs-sample/redis-sentinel:3
  environment:
    - affinity:service!=sentinel
  labels: 
    aliyun.scale: "3"
  restart: always
  links:
    - master:redis-master
    - slave
```

这里使用了预编译的sentinel镜像"registry.aliyuncs.com/acs-sample/redis-sentinel:3"

更重要是，引入了一些阿里云扩展使得对分布式应用更好地控制容器在宿主机节点的部署

* `aliyun.scale` 标签：描述了服务的实例数量
* `affinity:service` 环境变量描述了服务的部署约束：比如对于Redis slave而言，我们不希望在一个宿主机节点上同时部署master和slave，或多个slave，我们可以方便用示例中的方法描述这些约束。

关于这些的详尽解释请参见[帮助文档](https://yq.aliyun.com/go/articleRenderRedirect?url=https://help.aliyun.com/document_detail/26086.html)

一键部署之后，我们就已经有一个真正高可用的Redis集群了

1. 在这里master和2个slave部署到不同的宿主机节点中
2. 3个sentinel部署到不同的宿主机节点中\
   这样任何一个宿主机节点失效，都不会导致Redis集群失败

![14692757591755](http://img2.tbcdn.cn/L1/461/1/d746e495c96287c3b7870e54bd6aed5a62f96bac)

#### 总结 <a href="#id-3" id="id-3"></a>

文章介绍了如何在本地部署一个Redis集群，并利用Redis Sentinel实现自动化的主从切换。并在此基础上利用阿里云容器服务扩展，一键部署一个真正的高可用分布式Redis集群。

对于Redis而言，阿里云提供了云数据库 Redis 版，对于大部分对SLA有要求的客户我们建议在生产环境使用Redis云服务。但是如果大家对版本、配置有特殊要求的时候，使用Docker部署Redis也是非常方便的。

出于性能考虑，在Docker容器中运行Redis不建议采用bridge网络对外提供访问，如需对外部VM或应用提供服务建议采用host网络模式，并注意安全保护；如果只是对集群中容器提供redis访问，则容器服务默认提供的跨宿主机容器网络会提供优化而安全的网络配置。同时建议在Docker容器设置中，给Redis容器配置合适的内存设置。

#### 原文文章：<https://yq.aliyun.com/articles/57953>

方式二

## [CentOS 7下安装Redis](https://www.cnblogs.com/geekmao/p/11009603.html)

### 1、安装gcc环境 <a href="#an-zhuang-gcc-huan-jing" id="an-zhuang-gcc-huan-jing"></a>

```
sudo yum install gcc-c++
```

### 2、安装wget <a href="#an-zhuang-wget" id="an-zhuang-wget"></a>

```
sudo yum install wget
```

### 3、下载Redis源码包 <a href="#xia-zai-redis-yuan-ma-bao" id="xia-zai-redis-yuan-ma-bao"></a>

```
wget  http://download.redis.io/releases/redis-4.0.1.tar.gz
wget http://download.redis.io/releases/redis-2.8.17.tar.gz （试验安装可用）
```

### 4、解压redis-4.0.1.tar.gz安装包,并编译。 <a href="#jie-ya-redis4.0.1.tar.gz-an-zhuang-bao-bing-bian-yi" id="jie-ya-redis4.0.1.tar.gz-an-zhuang-bao-bing-bian-yi"></a>

```
tar xzf redis-2.8.17.tar.gz 

cd redis-4.0.1 

make
```

> 注意：如果在make过程中出现报错问题，那么就是由于gcc的环境安装有问题，请检查从新安装gcc环境。

### 5、安装 <a href="#an-zhuang" id="an-zhuang"></a>

```
make PREFIX=/usr/local/redis install
```

> 注意：安装命令执行完毕后会有如下目录\
> ![redis安装后目录效果](https://www.linuxidc.com/upload/2017_09/170930074190041.png)

#### Redis里面的bin目录结构 <a href="#redis-li-mian-de-bin-mu-lu-jie-gou" id="redis-li-mian-de-bin-mu-lu-jie-gou"></a>

![bin目录结构](https://www.linuxidc.com/upload/2017_09/170930074190042.png)

* redis-benchmark 性能测试工具
* redis-check-aof 文件修复工具
* redis-check-rdb rdb文件检查工具
* redis-cli 命令行客户端
* redis-server redis启动命令

### 6、从解压包文件中复制redis.conf文件到安装目录 <a href="#cong-jie-ya-bao-wen-jian-zhong-fu-zhi-redis.conf-wen-jian-dao-an-zhuang-mu-lu" id="cong-jie-ya-bao-wen-jian-zhong-fu-zhi-redis.conf-wen-jian-dao-an-zhuang-mu-lu"></a>

```
cp redis.conf /usr/local/redis
```

![拷贝redis.conf文件](https://www.linuxidc.com/upload/2017_09/170930074190043.png)

### 7、运行Redis（前台运行模式） <a href="#yun-hang-redis-qian-tai-yun-hang-mo-shi" id="yun-hang-redis-qian-tai-yun-hang-mo-shi"></a>

```
redis-server
```

![运行redis](https://www.linuxidc.com/upload/2017_09/170930074190044.png)

### 8、后台运行Redis <a href="#hou-tai-yun-hang-redis" id="hou-tai-yun-hang-redis"></a>

#### A、打开redis.conf文件 <a href="#a-da-kai-redis.conf-wen-jian" id="a-da-kai-redis.conf-wen-jian"></a>

```
sudo vim redis.conf
```

![打开redis.conf](https://www.linuxidc.com/upload/2017_09/170930074190046.png)

#### B、修改配置文件 <a href="#b-xiu-gai-pei-zhi-wen-jian" id="b-xiu-gai-pei-zhi-wen-jian"></a>

![修改配置文件](https://www.linuxidc.com/upload/2017_09/170930074190045.png)

#### C、将no改为yes <a href="#c-jiang-no-gai-wei-yes" id="c-jiang-no-gai-wei-yes"></a>

![将no改为yes](https://www.linuxidc.com/upload/2017_09/170930074190047.png)

#### D、保存文件并退出 <a href="#d-bao-cun-wen-jian-bing-tui-chu" id="d-bao-cun-wen-jian-bing-tui-chu"></a>

按下ESC键，输入

```
:wq
```

#### E、后台启动 <a href="#e-hou-tai-qi-dong" id="e-hou-tai-qi-dong"></a>

```
./bin/redis-server ./redis.conf
```

#### F、检查redis进程是否已经启动 <a href="#f-jian-cha-redis-jin-cheng-shi-fou-yi-jing-qi-dong" id="f-jian-cha-redis-jin-cheng-shi-fou-yi-jing-qi-dong"></a>

```
ps -ef | grep -i redis
```

### 9、关闭reids <a href="#guan-bi-reids" id="guan-bi-reids"></a>

* 方式1：杀死redis进程

  ```
  kill -9 进程id
  ```

  ![杀死redis进程](https://www.linuxidc.com/upload/2017_09/170930074190048.png)
* 方式2：正常关闭

  ```
  sudo ./bin/redis-cli shutdown
  ```

![正常关闭](https://www.linuxidc.com/upload/2017_09/170930074190049.png)

**注意：当以非root权限启动的reids，那么是无法用shutdown进行关闭的。它会报如下错误**\
![redis报错](https://www.linuxidc.com/upload/2017_09/1709300741900410.png)

***所以要解决此问题，可以使用kill方式杀死进程，然后在使用sudo方式启动redis***

***10.生产使用，使用systemctl管理***

***cd /etc/systemd/system***

***vim redis.service***![复制代码](https://common.cnblogs.com/images/copycode.gif)

```
[Unit]
Description=Redis
After=network.target

[Service]
ExecStart=/usr/local/redis/bin/redis-server /usr/local/redis/redis.conf  --daemonize no
ExecStop=/usr/local/redis/bin/redis-cli -h 127.0.0.1 -p 6379 shutdown

[Install]
WantedBy=multi-user.target
```

![复制代码](https://common.cnblogs.com/images/copycode.gif)

### 11、设置redis密码 <a href="#she-zhi-redis-mi-ma" id="she-zhi-redis-mi-ma"></a>

#### A、使用vim打开redis.conf文件 <a href="#a-shi-yong-vim-da-kai-redis.conf-wen-jian" id="a-shi-yong-vim-da-kai-redis.conf-wen-jian"></a>

```
sudo vim redis-conf
```

#### B、找到#requirepass foobared去掉注释 <a href="#b-zhao-dao-requirepassfoobared-qu-diao-zhu-shi" id="b-zhao-dao-requirepassfoobared-qu-diao-zhu-shi"></a>

#### C、将foobared改为自己的密码，我在这里改为requirepass 123456 <a href="#c-jiang-foobared-gai-wei-zi-ji-de-mi-ma-wo-zai-zhe-li-gai-wei-requirepass123456" id="c-jiang-foobared-gai-wei-zi-ji-de-mi-ma-wo-zai-zhe-li-gai-wei-requirepass123456"></a>

#### D、然后保存，重启服务 <a href="#d-ran-hou-bao-cun-zhong-qi-fu-wu" id="d-ran-hou-bao-cun-zhong-qi-fu-wu"></a>

转载：<https://www.linuxidc.com/Linux/2017-09/147198.htm>

##


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://darren.gitbook.io/project/devops/untitled-2.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
