云计算必备良方-Redis集群架构

Posted Friends of the wind

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了云计算必备良方-Redis集群架构相关的知识,希望对你有一定的参考价值。

一、Redis集群简介

Redis Cluster 是 redis的分布式解决方案,在3.0版本正式推出当遇到单机、内存、并发、流量等瓶颈时,可以采用Cluster架构方案达到负载均衡目的。

Redis Cluster之前的分布式方案有两种:

1)客户端分区方案: 优点分区逻辑可控,缺点是需要自己处理数据路由,高可用和故障转移等。

2)代理方案: 优点是简化客户端分布式逻辑和升级维护便利,缺点加重架构部署和性能消耗。官方提供的 Redis Cluster集群方案,解决了集群方面的问题

数据分布
分布式数据库首先要解决把整个数据库集按照分区规则映射到多个节点的问题,即把数据集划分到多个节点上,
每个节点负责整体数据的一个子集,需要关注的是数据分片规则,Redis Cluster采用哈希分片规则。

二、案例

1.目录规划

redis安装目录:
/opt/redis_cluster/redis_{PORT}/{conf,logs,pid}
redis数据目录:
/data/redis_cluster/redis_{PORT}/redis_{PORT}.rdb
redis运维脚本目录:
/root/scripts/redis_shell.sh

2.集群拓扑

Redis1上面搭建两个Redis服务,以端口区分,6380、6381,依次类推,这样我们用三台虚拟机模拟6台虚拟机的集群环境。

节点名IP
Redis1192.168.2.130
Redis2192.168.2.135
Redis3192.168.2.136

3.步骤

先部署一台服务器上的2个集群节点,把文件发送到其他主机修改IP地址,启动服务。

Redis安装
(1)redis1操作

mkdir -p /opt/redis_cluster/redis_{6380,6381}/{conf,logs,pid}
mkdir -p /data/redis_cluster/redis_{6380,6381}

先安装redis,具体步骤参考上节教程

创建6380的配置文件:
cat >/opt/redis_cluster/redis_6380/conf/redis_6380.conf<<EOF
bind 192.168.2.130
port 6380
daemonize yes
pidfile “/opt/redis_cluster/redis_6380/pid/redis_6380.pid”
logfile “/opt/redis_cluster/redis_6380/logs/redis_6380.log”
dbfilename “redis_6380.rdb”
dir “/data/redis_cluster/redis_6380/”
cluster-enabled yes
cluster-config-file nodes_6380.conf
cluster-node-timeout 15000
EOF

以修改6380配置的方式,创建6381的配置文件:

cd /opt/redis_cluster/
cp redis_6380/conf/redis_6380.conf redis_6381/conf/redis_6381.conf
sed -i ‘s#6380#6381#g’ redis_6381/conf/redis_6381.conf
redis-server /opt/redis_cluster/redis_6380/conf/redis_6380.conf
redis-server /opt/redis_cluster/redis_6381/conf/redis_6381.conf
验证:

(2)复制redis1的安装和数据目录到redis2、redis3

scp -rp /opt/redis_cluster/ root@192.168.2.135:/opt
scp -rp /opt/redis_cluster/ root@192.168.2.137:/opt

(3)redis2操作:

cd /opt/redis_cluster/redis
make install
find /opt/redis_cluster/redis_638* -type f -name “*.conf”|xargs sed -i “s#130#135#g”
mkdir -p /data/redis_cluster/redis_{6380,6381}
redis-server /opt/redis_cluster/redis_6380/conf/redis_6380.conf
redis-server /opt/redis_cluster/redis_6381/conf/redis_6381.conf

(4)redis3操作

cd /opt/redis_cluster/redis
make install
find /opt/redis_cluster/redis_638* -type f -name “*.conf”|xargs sed -i “s#130#136#g”
mkdir -p /data/redis_cluster/redis_{6380,6381}
redis-server /opt/redis_cluster/redis_6380/conf/redis_6380.conf
redis-server /opt/redis_cluster/redis_6381/conf/redis_6381.conf


节点发现使用命令: CLUSTER MEET {IP} {PORT}
提示:在集群内任意一台机器执行此命令就可以,把所有节点添加到集群

Redis Cluster手动分配槽位

分配主从

验证:

脚本测试

.模拟故障转移
1)模拟redis1故障:

2)查看群集节点状态:

3)再启动redis1的服务,重回master(不使用命令夺回master,即便恢复启动,还是slave)

使用命令后查看:Redis1的6380重回master

自动搭建部署Redis Cluster

手动搭建集群需要很多步骤,当集群节点众多时,必然会加大搭建集群的复杂度和运维成本。
因此官方提供了 redis-trib.rb的工具方便我们快速搭建集群。redis-trib.rb是采用 Ruby 实现的 redis 集群管理工具,内部通过 Cluster相关命令帮我们简化集群创建、检查、槽迁移和均衡等常见运维操作,使用前要安装 ruby 依赖环境。

1)前提准备:
停掉所有的节点,然后清空数据,恢复成一个全新的集群,所有机器执行命令
pkill redis
rm -rf /data/redis_cluster/redis_6380/*
rm -rf /data/redis_cluster/redis_6381/*

全部清空之后启动所有的节点,所有机器执行
redis-server /opt/redis_cluster/redis_6380/conf/redis_6380.conf
redis-server /opt/redis_cluster/redis_6381/conf/redis_6381.conf

2)安装命令:注意新版本redis不需安装,直接采用步骤:3)
yum makecache fast
yum install rubygems
gem sources --remove https://rubygems.org/
gem sources -a http://mirrors.aliyun.com/rubygems/
gem update –system
gem install redis -v 3.3.5

redis1执行创建集群命令(提示,输入yes,同意)
cd /opt/redis_cluster/redis/src/

检查集群完整性

3)或直接使用redis-cli命令*****
创建群集:
redis-cli --cluster create --cluster-replicas 1 192.168.100.99:6380 192.168.100.32:6380 192.168.100.245:6380 192.168.100.99:6381 192.168.100.32:6381 192.168.100.245:6381

检查完整性:
redis-cli --cluster check 192.168.100.99:6380

工具扩容节点

Redis集群的扩容操作可分为以下几个步骤
1)准备新节点
2)加入集群
3)迁移槽和数据

redis1上创建2个新节点
创建配置文件:
mkdir -p /opt/redis_cluster/redis_{6390,6391}/{conf,logs,pid}
mkdir -p /data/redis_cluster/redis_{6390,6391}
cd /opt/redis_cluster/
cp redis_6380/conf/redis_6380.conf redis_6390/conf/redis_6390.conf
cp redis_6380/conf/redis_6380.conf redis_6391/conf/redis_6391.conf
sed -i ‘s#6380#6390#g’ redis_6390/conf/redis_6390.conf
sed -i ‘s#6380#6391#g’ redis_6391/conf/redis_6391.conf

启动节点
redis-server /opt/redis_cluster/redis_6390/conf/redis_6390.conf
redis-server /opt/redis_cluster/redis_6391/conf/redis_6391.conf

发现节点(将节点加入集群)

分配slots
输入分配的slots数:4096
再输入6390的id号
再输入all

配置6391 slave 6390:

验证:

工具收缩节点

流程说明
1).首先需要确定下线节点是
否有负责的槽;

如果是,需要把槽迁移到其他节点,保证节点下线后整个集群槽节点映射的完整性.
2).当下线节点不再负责槽或者本身是从节点时,
就可以通知集群内其他节点忘记下线节点,当所有的节点忘记该节点后可以正常关闭.

这里我们准备将刚才新添加的节点下线,也就是6390和6391
收缩和扩容迁移的方向相反,6390变为源节点,其他节点变为目标节点,源节点把自己负责的4096个槽均匀的迁移到其他节点上,.

(1)旧版本
由于redis-trib…rb reshard命令只能有一个目标节点,因此需要执行3次reshard命令,分别迁移1365,1365,1366个槽.

操作命令:
cd /opt/redis_cluster/redis/src/
./redis-trib.rb reshard 192.168.100.99:6380
How many slots do you want to move (from 1 to 16384)? 1365
输入6380的id
输入6390的id
done

忘记节点
由于我们的集群是做了高可用的,所以当主节点下线的时候从节点也会顶上,所以最好我们先下线从节点,然后在下线主节点

cd /opt/redis_cluster/redis/src/
./redis-trib.rb del-node 192.168.100.99:6391 ID
./redis-trib.rb del-node 192.168.100.99:6390 ID

(2)新版本
移除下线节点的槽位:

本课案例中分三次移除:提示,输入yes确定进行移除。
1365 给redis1的6380

1366 给redis2的6380

1365 给redis3的6380

查看验证:看不到6390后面的槽位,证明移除成功

移除后遗忘下线节点:
redis-cli -c -h 192.168.2.130 -p 6380 cluster forget 6390的ID

redis-cli -c -h 192.168.2.130 -p 6380 cluster forget 6391的ID

查看验证:

三、扩展

Redis集群常用命令

集群(cluster)
CLUSTER INFO 打印集群的信息
CLUSTER NODES 列出集群当前已知的所有节点(node),以及这些节点的相关信息。
节点(node)
CLUSTER MEET 将 ip 和 port 所指定的节点添加到集群当中,让它成为集群的一份子。
CLUSTER FORGET <node_id> 从集群中移除 node_id 指定的节点。
CLUSTER REPLICATE <node_id> 将当前节点设置为 node_id 指定的节点的从节点。
CLUSTER SAVECONFIG 将节点的配置文件保存到硬盘里面。
槽(slot)
CLUSTER ADDSLOTS [slot …] 将一个或多个槽(slot)指派(assign)给当前节点。
CLUSTER DELSLOTS [slot …] 移除一个或多个槽对当前节点的指派。
CLUSTER FLUSHSLOTS 移除指派给当前节点的所有槽,让当前节点变成一个没有指派任何槽的节点。
CLUSTER SETSLOT NODE <node_id> 将槽 slot 指派给 node_id 指定的节点,如果槽已经指派给另一个节点,那么先让另一个节点删除该槽>,然后再进行指派。
CLUSTER SETSLOT MIGRATING <node_id> 将本节点的槽 slot 迁移到 node_id 指定的节点中。
CLUSTER SETSLOT IMPORTING <node_id> 从 node_id 指定的节点中导入槽 slot 到本节点。
CLUSTER SETSLOT STABLE 取消对槽 slot 的导入(import)或者迁移(migrate)。
键 (key)
CLUSTER KEYSLOT 计算键 key 应该被放置在哪个槽上。
CLUSTER COUNTKEYSINSLOT 返回槽 slot 目前包含的键值对数量。CLUSTER GETKEYSINSLOT 返回 count 个 slot 槽中的键。

Redis运维工具

1.运维脚本(管理Redis)
[root@redis1 ~]# cat redis_shell.sh

#!/bin/bash

USAG(){
    echo "sh $0 {start|stop|restart|login|ps|tail} PORT"
}
if [ "$#" = 1 ]
then
    REDIS_PORT='6379'
elif 
    [ "$#" = 2 -a -z "$(echo "$2"|sed 's#[0-9]##g')" ]
then
    REDIS_PORT="$2"
else
    USAG
    exit 0
fi

REDIS_IP=$(hostname -I|awk '{print $1}')
PATH_DIR=/opt/redis_cluster/redis_${REDIS_PORT}/
PATH_CONF=/opt/redis_cluster/redis_${REDIS_PORT}/conf/redis_${REDIS_PORT}.conf
PATH_LOG=/opt/redis_cluster/redis_${REDIS_PORT}/logs/redis_${REDIS_PORT}.log

CMD_START(){
    redis-server ${PATH_CONF}
}

CMD_SHUTDOWN(){
    redis-cli -c -h ${REDIS_IP} -p ${REDIS_PORT} shutdown
}

CMD_LOGIN(){
    redis-cli -c -h ${REDIS_IP} -p ${REDIS_PORT}
}

CMD_PS(){
    ps -ef|grep redis
}

CMD_TAIL(){
    tail -f ${PATH_LOG}
}

case $1 in
    start)
        CMD_START
        CMD_PS
        ;;
    stop)
        CMD_SHUTDOWN
        CMD_PS
        ;;
    restart)
        CMD_START
        CMD_SHUTDOWN
        CMD_PS
        ;;
    login)
        CMD_LOGIN
        ;;
    ps)
        CMD_PS
        ;;
    tail)
        CMD_TAIL
        ;;
    *)
        USAG
esac

2.数据导入导出工具
需求背景
刚切换到redis集群的时候肯定会面临数据导入的问题,所以这里推荐使用redis-migrate-tool工具来导入单节点数据到集群里
官方地址:
http://www.oschina.net/p/redis-migrate-tool
安装工具

cd /opt/redis_cluster/
git clone https://github.com/vipshop/redis-migrate-tool.git
cd redis-migrate-tool/
autoreconf -fvi
./configure
make && make install
创建配置文件

[root@redis1 ~]# cat redis_6379_to_6380.conf
[source]
type: single
servers:

  • 192.168.100.99:6379

[target]
type: redis cluster
servers:

  • 192.168.100.99:6380

[common]
listen: 0.0.0.0:8888
source_safe: true
生成测试数据

[root@redis1 ~]# cat input_key.sh

#!/bin/bash
for i in $(seq 1 1000)
do
    redis-cli -c -h redis1 -p 6379 set k_${i} v_${i} && echo "set k_${i} is ok"
done

执行导入命令

[root@redis1 ~]# redis-migrate-tool -c redis_6379_to_6380.conf
数据校验

[root@redis1 ~]# redis-migrate-tool -c redis_6379_to_6380.conf -C redis_check

3.分析键值大小
需求背景
redis的内存使用太大键值太多,不知道哪些键值占用的容量比较大,而且在线分析会影响性能.
安装工具

yum install python-pip gcc python-devel
cd /opt/
git clone https://github.com/sripathikrishnan/redis-rdb-tools
cd redis-rdb-tools
python setup.py install

使用方法
cd /data/redis_cluster/redis_6380/
rdb -c memory redis_6380.rdb -f redis_6380.rdb.csv
分析rdb并导出

awk -F ‘,’ ‘{print $4,$2,$3,$1}’ redis_6380.rdb.csv |sort > 6380.txt

4.监控过期键

需求背景
因为开发重复提交,导致电商网站优惠卷过期时间失效
问题分析
如果一个键已经设置了过期时间,这时候在set这个键,过期时间就会取消
解决思路
如何在不影响机器性能的前提下批量获取需要监控键过期时间

1.Keys * 查出来匹配的键名。然后循环读取ttl时间

2.scan * 范围查询键名。然后循环读取ttl时间
Keys 重操作,会影响服务器性能,除非是不提供服务的从节点
Scan 负担小,但是需要去多次才能取完,需要写脚本

脚本内容:

Vim 01get_key.sh

#!/bin/bash
key_num=0
> key_name.log
for line in $(cat key_list.txt)
do
    while true
    do
        scan_num=$(redis-cli -h 192.168.47.75 -p 6380 SCAN ${key_num} match ${line}\\* count 1000|awk 'NR==1{print $0}')
        key_name=$(redis-cli -h 192.168.47.75 -p 6380 SCAN ${key_num} match ${line}\\* count 1000|awk 'NR>1{print $0}')
        echo ${key_name}|xargs -n 1 >> key_name.log
        ((key_num=scan_num))
        if [ ${key_num} == 0 ]
           then
           break
        fi
    done
done

以上是关于云计算必备良方-Redis集群架构的主要内容,如果未能解决你的问题,请参考以下文章

科技云报道:数字化转型东风已至,云计算如何为医药行业开良方?

科技云报道:数字化转型东风已至,云计算如何为医药行业开良方?

助我拿下大厂offer,架构师必备技能

6.《持续演进的Cloud Native 云原生架构下微服务最佳实践》读书笔记-第三章基于Codis实现Redis分布式缓存集群

一线互联网架构师筑基必备技能之Java篇,不愧是大佬

Linux云计算-MySQL-高可用集群架构-MHA 架构