Redis Cluster 集群

一. 介绍

  Redis集群搭建的方式有多种,例如使用zookeeper等,但从redis 3.0之后版本支持redis-cluster集群,Redis-Cluster采用无中心结构,每个节点保存数据和整个集群状态,每个节点都和其他所有 节点连接。redis cluster自动master + slave复制和读写分离,master+slave高可用和主备切换,支持多个master的hash slot支持数据分布式存储。

二. Redis Cluster配置属性

cluster-enabled <yes/no>

cluster-config-file <filename>:这是指定一个文件,供cluster模式下的redis实例将集群状态保存在那里,包括集群中其他机器的信息,比如节点的上线和下限,故障转移,不是我们去维护的,给它指定一个文件,让redis自己去维护的

cluster-node-timeout <milliseconds>:节点存活超时时长,超过一定时长,认为节点宕机,master宕机的话就会触发主备切换,slave宕机就不会提供服务

三. 创建和配置

3.1 创建目录

/etc/redis(存放redis的配置文件)
/var/redis/6379(存放redis的持久化文件)

mkdir -p /etc/redis-cluster
mkdir -p /var/log/redis
mkdir -p /var/redis/7001

3.2 修改配置文件

(redis.conf 重命名 7001.conf)

port 7001
cluster-enabled yes
cluster-config-file /etc/redis-cluster/node-7001.conf
cluster-node-timeout 15000
daemonize yes
pidfile /var/run/redis_7001.pid
dir /var/redis/7001
logfile /var/log/redis/7001.log
bind 192.168.0.5
appendonly yes

存放路径如图所示:

未分类

将上面的配置文件(注意修改配置属性),在各虚拟机/etc/redis下依次放2个,分别为:

192.168.0.5: 7001.conf 7002.conf
192.168.0.6: 7003.conf 7004.conf
192.168.0.7: 7005.conf 7006.conf

3.3 启动脚本配置

cp /usr/local/redis-3.2.8/utils/redis_init_script /etc/init.d/redis_7001
vi /etc/init.d/redis_7001

#!/bin/sh
#
# Simple Redis init.d script conceived to work on Linux systems
# as it does use of the /proc filesystem.
# chkconfig:   2345 90 10

# description:  Redis is a persistent key-value database

# 每个启动脚本内,都修改对应的端口号
REDISPORT=7001
EXEC=/usr/local/bin/redis-server
CLIEXEC=/usr/local/bin/redis-cli

PIDFILE=/var/run/redis_${REDISPORT}.pid
CONF="/etc/redis/${REDISPORT}.conf"

case "$1" in
    start)
        if [ -f $PIDFILE ]
        then
                echo "$PIDFILE exists, process is already running or crashed"
        else
                echo "Starting Redis server..."
                $EXEC $CONF
        fi
        ;;
    stop)
        if [ ! -f $PIDFILE ]
        then
                echo "$PIDFILE does not exist, process is not running"
        else
                PID=$(cat $PIDFILE)
                echo "Stopping ..."
                $CLIEXEC -p $REDISPORT shutdown
                while [ -x /proc/${PID} ]
                do
                    echo "Waiting for Redis to shutdown ..."
                    sleep 1
                done
                echo "Redis stopped"
        fi
        ;;
    *)
        echo "Please use start or stop as first argument"
        ;;
esac

分别在每个虚拟机/etc/init.d下,放6个启动脚本,分别为:

  • 192.168.0.5: redis_7001 redis_7002
  • 192.168.0.6: redis_7003 redis_7004
  • 192.168.0.7: redis_7005 redis_7006

然后分别在3台机器上,启动6个redis实例

[root@sw01 utils]# cd /etc/init.d/
[root@sw01 utils]# ./redis_7001 start
[root@sw01 utils]# ps -ef | grep redis
root     26227  1  0 Jan21 ?  00:03:23 /usr/local/bin/redis-server 192.168.0.5:7002 [cluster]
root     26355  1  0 Jan21 ?  00:03:08 /usr/local/bin/redis-server 192.168.0.5:7001 [cluster]
root     26659 26254  0 04:44 pts/0    00:00:00 grep redis

四. 安装ruby创建集群

只需要在一台服务器安装即可

3.1 下载安装

[root@sw01 utils]# wget https://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.1.tar.gz
[root@sw01 utils]# tar -zxvf ruby-2.3.1.tar.gz
[root@sw01 utils]# ./configure -prefix=/usr/local/ruby
[root@sw01 utils]# make && make install
[root@sw01 utils]# cd /usr/local/ruby
[root@sw01 utils]# cp bin/ruby /usr/local/bin
[root@sw01 utils]# cp bin/gem /usr/local/bin

3.2 centos安装较高版本ruby2.2+(RVM 安装)

centos安装较高版本ruby2.2+(RVM 安装)

3.3 Redis配置集群遇到问题及解决方法

Redis配置集群遇到问题及解决方法

3.4 创建集群

[root@sw01 utils]# cp /usr/local/redis-3.2.8/src/redis-trib.rb /usr/local/bin
[root@sw01 utils]# redis-trib.rb create --replicas 1 192.168.0.5:7001 192.168.0.5:7002 192.168.0.6:7003 192.168.0.6:7004 192.168.0.7:7005 192.168.0.7:7006
输入:yes
[root@sw01 utils]# redis-trib.rb check 192.168.0.5:7001
>>> Performing Cluster Check (using node 192.168.0.5:7001)
S: bcb8d971ed0875c173f50af950f6b7590b79510d 192.168.0.5:7001
   slots: (0 slots) slave
   replicates dedb9de54b51aa09106c772d743456b31e5d884f
M: 9617ff44c32b9afe9414724057cfdbeb65b492ab 192.168.0.7:7006
   slots:10923-16383 (5461 slots) master
   1 additional replica(s)
M: bb4313206fbacf94992f3b1de33e82373f9eb769 192.168.0.6:7003
   slots:5461-10922 (5462 slots) master
   1 additional replica(s)
S: 1aa3316590a71b6f788a31cebc109a76b654c5fb 192.168.0.7:7005
   slots: (0 slots) slave
   replicates 9617ff44c32b9afe9414724057cfdbeb65b492ab
S: f5648903d98526ee798b7aa7dfcc3f747652a229 192.168.0.5:7002
   slots: (0 slots) slave
   replicates bb4313206fbacf94992f3b1de33e82373f9eb769
M: dedb9de54b51aa09106c772d743456b31e5d884f 192.168.0.6:7004
   slots:0-5460 (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.

配置完成

Redis Cluster的图文讲解

1.1 Redis-Cluster简介

1.1.1 什么是Redis-Cluster

为何要搭建Redis集群。Redis是在内存中保存数据的,而我们的电脑一般内存都不大,这也就意味着Redis不适合存储大数据,适合存储大数据的是Hadoop生态系统的Hbase或者是MogoDB。Redis更适合处理高并发,一台设备的存储能力是很有限的,但是多台设备协同合作,就可以让内存增大很多倍,这就需要用到集群。

Redis集群搭建的方式有多种,例如使用客户端分片、Twemproxy、Codis等,但从redis 3.0之后版本支持redis-cluster集群,它是Redis官方提出的解决方案,Redis-Cluster采用无中心结构,每个节点保存数据和整个集群状态,每个节点都和其他所有节点连接。其redis-cluster架构图如下:

未分类

客户端与 redis 节点直连,不需要中间 proxy 层.客户端不需要连接集群所有节点连接集群中任何一个可用节点即可。
所有的 redis 节点彼此互联(PING-PONG 机制),内部使用二进制协议优化传输速度和带宽.

1.1.2分布存储机制-槽

(1)redis-cluster 把所有的物理节点映射到[0-16383]slot 上,cluster 负责维护nodeslotvalue
(2)Redis 集群中内置了 16384 个哈希槽,当需要在 Redis 集群中放置一个 key-value 时,redis 先对 key 使用 crc16 算法算出一个结果,然后把结果对 16384 求余数,这样每个key 都会对应一个编号在 0-16383 之间的哈希槽,redis 会根据节点数量大致均等的将哈希槽映射到不同的节点。

例如三个节点:槽分布的值如下:

  • SERVER1: 0-5460
  • SERVER2: 5461-10922
  • SERVER3: 10923-16383

1.1.3分布存储机制-槽

(1)redis-cluster 把所有的物理节点映射到[0-16383]slot 上,cluster 负责维护nodeslotvalue

(2)Redis 集群中内置了 16384 个哈希槽,当需要在 Redis 集群中放置一个 key-value 时,redis 先对 key 使用 crc16 算法算出一个结果,然后把结果对 16384 求余数,这样每个key 都会对应一个编号在 0-16383 之间的哈希槽,redis 会根据节点数量大致均等的将哈希槽映射到不同的节点。

例如三个节点:槽分布的值如下:

  • SERVER1: 0-5460
  • SERVER2: 5461-10922
  • SERVER3: 10923-16383

未分类

1.2 总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值。

Redis Cluster 实践

背景

redis 这个 gem 在最新的 4.1 版中开始支持 Redis Cluster。

开发环境

我们需要在开发环境搭建一个 Redis Cluster,最方便快捷的方法是使用 docker 和 docker-compose,并且使用配置好的 image。

在 docker-compose.yml 中添加下列代码

version: '3'
services:
  redis-cluster:
    image: grokzen/redis-cluster
    environment:
     - IP=0.0.0.0
    ports:
      - '7000-7007:7000-7007'

使用 docker-compose up -d 启动服务即可。

更新代码

在 Gemfile 中设置 redis gem 的版本为 4.1

gem "redis", "~> 4.1"

在 application.rb 中修改 session_store 和 cache_store

Rails.application.configure do
  # Redis Session Store (redis-rails Gem)
  config.session_store :redis_store, servers: { cluster: %w[redis://127.0.0.1:7000] }, expires_in: 1.month

  # Redis Cache Store (redis-rails Gem)
  config.cache_store = :redis_store, { cluster: %w[redis://127.0.0.1:7000] }

  # Redis Cache Store (ActiveSupport)
  config.cache_store = :redis_cache_store, { cluster: %w[redis://127.0.0.1:7000] }
end

在其他地方使用 Redis Cluster

redis = Redis.new(cluster: %w[redis://127.0.0.1:7000])

分片

从单机变成集群之后,数据分片了,分散到不同机器,但是实际需求要求相关联的 key 分配到相同机器。

因为业务或者性能问题,我们会使用 Redis 的 pipelined、multi 和 Rails.cache.read_multi,这些场景下都需要 key 分配到相同机器。

但是 Redis Cluster 的分片方案是服务端提供分片,规则不是客户端控制的。

针对这些场景 Redis Cluster 提供了 Keys hash tags 的功能,简单来说是:

当一个 key 包含 {} 的时候,就不对整个 key 做 hash,而仅对 {} 包括的字符串做 hash。

redis = Redis.new(cluster: %w[redis://127.0.0.1:7000])

redis.mget('key1', 'key2')
#=> Redis::CommandError (CROSSSLOT Keys in request don't hash to the same slot)

redis.mget('{key}1', '{key}2')
#=> [nil, nil]

总结

本文只是一个简单的例子,不能在生产环境中直接使用。

在生产环境需要考虑 Redis 的各个客户端,同时要考虑数据迁移和兼容的问题,升级到 Redis Cluster 要非常谨慎和细心。