redis cluster集群方案详解

 1 概要介绍

1.1 应用场景

缓存:相对静态、或变化缓慢的数据,可以利用缓存降低数据库IO压力,提升性能

分布式锁:集群环境下对同一个资源的竞争,可借助redis来实现对资源加锁。可查阅redis官方redlock相关介绍

秒杀:在redis中进行预处理,充当缓冲,将处理结果延迟持久化到数据库。规避高并发对DB的压力

计算器:每次操作加1,redis天然支持计数的api操作

消息队列:功能太简单,一般不用

分布式session

限数:每60秒获取一次验证码,设置key、value、失效时间1分钟到redis,每次获取校验码进行先验证redis是否有值即可

防爬虫缓存穿透:

请求透过缓存层,直接命中DB,并发量大,造成DB层宕机

造成缓存穿透的基本原因有两个。第一,自身业务代码或者数据出现问 题,第二,一些恶意攻击、爬虫等造成大量空命中。 解决方案:在redis中保存失效期较短的空缓存。

1.2 不适合做什么

不适合用来做长期持久化数据

不适合用来做大数据量的频繁存取,容易阻塞。适合短频快的数据存取。

1.3数据结构

key-value键值对,value的数据类型包括:string、hash、set、zset(有序集合)、list等。redis是用C语言编写的,如果对数据结构与算法还有印象的同学应该很亲切。

常用的string 与hash,学会运用这两类即可。

1.4单线程架构

redis接收客户端的请求,把执行命令插入一个队列中,然后逐个被执行。因为是单线程架构,所以不会有两个命令在同一时刻执行,redis他自身是线程安全的,这个特性很重要。

单线程为什么还这么快?redis的命令操作都是在内存中进行,可以在纳秒级别就处理完,使用了epoll非阻塞IO(想深入了解可以去查阅网上资料),单线程也就省却了线程切换的CPU消耗。

了解单线程模型有助于我们做出更好的部署决策,如果在一台多核主机上部署一个实例,太浪费CPU资源了。

 

2 架构原理

redis官方集群模式包括:单节点、一主一从,一主多从、哨兵模式、cluster模式等。开源方案codis实现的代理模式等等。

其他模式的优缺点这里就不讲了,这里讲讲cluster模式的优点:

高性能:客户端直连模式,没有代理转发。redis自身处理客户端请求飞快,纳秒级别

高并发:普通的硬件配置,单节点可支持10WQPS

高可用:单个主节点宕机不影响整体集群的服务能力,可通过自动健康检查、故障转移将从节点升级为主节点

可弹性扩展:在线水平扩展数据容量、吞吐量、主从节点个数等

2.1 redis cluster方案架构图


 2.2 方案说明

以上图所示的三主三从集群为例,每个主节点处理各自的数据,提供读写能力,从节点异步复制主节点的数据。假设给每个redis实例分配了8G的最大内存,总的数据容量大小为24G(如果想继续扩充数据容量,继续加主节点)。单个redis实例的最大内存不建议超过10G。

2.3 数据分布

cluster集群方案,采用的是虚拟槽分区,槽范围是0-16383,有16384个槽。集群中有3个主节点,每个节点大致负责5500个槽的读写,节点会维护自身负责的虚拟槽。

键所对应的哈希值通过如下公式计算:CRC16(key)%16384。目前常见的redisson、jedis等客户端工具都已实现,推荐使用redisson,jedis可以弃疗。

redisson客户端初始化的时候,会加载集群的元数据信息,创建连接池。包括IP 端口 哈希槽的映射关系。

在实际使用时,set key value命令会计算hash值,把key-value设置到对应的主节点上。

 2.4 数据持久化 RDB VS AOF

 2.4.1 RDB全量持久化

父进程执行fork操作创建子进程,fork操作过程中父进程会阻塞,阻塞的时间跟所用内存大小成正比,要求redis实例最大不要超过10G。由子进程去创建最新的RDB文件。

什么时候会发生持久化操作呢?1、人工执行bgsave命令;2、达到配置文件中指定的约束条件

rdb文件放置在哪里? dbfilename 配置项指定

RDB的优点:redis重启恢复数据的时候速度很快

RDB的缺点: 无法实时持久化,fork会阻塞父进程

关闭RDB配置 :save “”

2.4.2 AOF增量持久化

默认是关闭的,配置 appendonly yes 开启。appendfilename 指定文件名,保存的路径与RDB一样,通过dir指定

所有的操作命令会追加到aof_buf缓冲区,根据策略appendsync everysec 每秒同步到磁盘上的AOF文件。

aof文件重写压缩过程中也会执行fork操作。

redis重启时可以加载aof文件进行数据恢复。

RDB与AOF各有优劣,根据实际业务场景选择合适的方案,甚至不用。

2.4.3  redis启动过程的数据恢复

2.4 集群通信

每个节点会随机对集群中的部分节点发生ping命令,判断其他节点的健康状态,

3 集群安装与配置

3.1 关键配置

protected-mode no 允许外部主机访问

cluster-enabled yes  配置为cluster 模式

cluster-config-file nodes-6379.conf  集群节点配置信息,包括nodeid,集群信息。此文件非常关键,要确保故障转移或者重启的时候此文件还在,所以如果在docker环境下要外挂到外部存储

cluster-node-timeout 2000  节点连接超时,如果集群规模小,都在同一个网络环境下,可以配置的短些,更快的做故障转移

slowlog-log-slower-than  慢查询日志,用于性能分析,生产环境可设置为1000(微妙)

slowlog-max-len   保存慢查询的队列长度 ,设置为1000

maxclients  集群支持的最大连接 50000

cluster-slave-validity-factor 设置为0,如果master slave都挂掉,slave跟master失联又超过这个数值*timeout的数值,就不会发起选举了。如果设置为0,就是永远都会尝试发起选举,尝试从slave变为mater

cluster-require-full-coverage  设置为no,默认为yes,故障发现到自动 完成转移期间整个集群是不可用状态,对于大多数业务无法容忍这种情况, 因此要设置为no,当主节点故障时只影 响它负责槽的相关命令执行,不会影响其他主节点的可用性

save “”  通用配置,关闭RDB持久化,只使用AOF。

maxmemory 8GBRedis默认无限使用服务器内存,为防止极端情况下导致系统内存耗 尽,建议所有的Redis进程都要配置maxmemory,要保证机器本身有30%左右的闲置内存

maxmemory-policy  volatile-lru 内存剔除策略

logfile “”  默认为空,则在控制台打印,否则输出日志到指定的log文件

3.2 注意事项

操作系统本身的最大连接数设置open  files建议设置为65535,redis的最大连接数受此限制。

ulimit -a 可以查看所有配置

修改: vim /etc/security/limits.conf

主节点平均分配到不同的机器上,否则容易造成单点故障以及复制风暴。

操作系统关闭THP:

vim /etc/rc.d/rc.local

增加下列内容:

if test -f /sys/kernel/mm/transparent_hugepage/enabled; then

echo never > /sys/kernel/mm/transparent_hugepage/enabled

fi

if test -f /sys/kernel/mm/transparent_hugepage/defrag; then

echo never > /sys/kernel/mm/transparent_hugepage/defrag

fi

然后给rc.local添加可执行权限:chmod +x /etc/rc.d/rc.local。重启生效


slave-read-only集群模式下无效,cluster集群模式下,从节点默认是处于冷备的状态,不提供读写服务。需要客户端去开启从节点的readonly,推荐用redisson java客户端工具,jedis不支持。

redis总共16个数据库,默认使用第0个数据库,集群模式下只能用第0数据库。多数据库功能就算单节点部署方案也不建议使用,这点知道即可。

3.3 修改linux连接数限制

切换到root用户修改配置sysctl.conf 

vim /etc/sysctl.conf

添加配置:

vm.max_map_count=655360

vm.overcommit_memory=1

net.core.somaxconn= 1024

vim /etc/security/limits.conf 

添加

* soft nofile 65536

* hard nofile 65536

* soft nproc 65536

* hard nproc 65536

vi /etc/security/limits.d/20-nproc.conf 

 #加大普通用户限制 也可以改为unlimited

 * soft nproc 40960 

 root soft nproc unlimited


reboot或者重新登录

3.4 linux环境下安装

wget http://download.redis.io/releases/redis-4.0.7.tar.gz

tar xzf redis-4.0.7.tar.gz

cd redis-4.0.7

yum -y install gcc

编译安装:make install 

Redis编译安装之后,src和/usr/local/bin目录下多了几个以redis开头可执行文 件

启动redis:

cd  /redis/data  当前工作目录是默认的根目录

redis-server  /redis/data/redis.conf   

 配置文件方式启动方式,也是推荐的方案,将定制的配置文件放在/redis/data目录,

 /redis/data此时就是根目录

停止redis:redis-cli shutdown                                不要用kill,太粗暴,可能导致数据丢失

集群至少需要6节点,3主3从,准备至少6个节点。

3.4.1 启动节点

启动6个节点:redis-server redis.conf ,确保该目录下没有AOF RDB文件,否则不能加入集群。


3.4.2 节点握手

  节点彼此之间通过gossip协议(“谣言”协议了解一下),一个节点连接其他5个节点即可。

127.0.0.1:6379>cluster meet 127.0.0.1 6382 

>cluster  nodes  查看集群信息

>cluster info  查看集群状态,此时不可用

3.4.3  分配槽

redis-cli -h 127.0.0.1 -p 6379 cluster addslots {0...5461}

3.4.4 分配子节点

127.0.0.1:6382>cluster replicate cfb28ef1deee4e0fa78da86abe5d24566744411e 

3.5 借助redis-trib工具进行自动化创建集群

手工创建集群过程很繁琐。官方提供了redis-trib.rb工具来实现集群管理。

3.5.1 ruby环境准备

-- 下载ruby 

wget https:// cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.1.tar.gz 

-- 安装ruby 

tar xvf ruby-2.3.1.tar.gz 

cd  ruby-2.3.1

./configure -prefix=/usr/local/ruby 

make

make install 

cd /usr/local/ruby 

sudo cp bin/ruby /usr/local/bin 

sudo cp bin/gem /usr/local/bin

--安装rubygem redis依赖

wget http:// rubygems.org/downloads/redis-3.3.0.gem 

gem install -l redis-3.3.0.gem 

如果提示缺少zlib ,


进入ruby项目文件夹:

#cd ext/zlib

#ruby ./extconf.rb

#make 

#make install

---安装redis-trib.rb

sudo cp /{redis_home}/src/redis-trib.rb /usr/local/bin

--测试是否安装成功

>redis-trib.rb 

3.5.2 启动6个节点

3.5.3 创建集群

redis-trib.rb create --replicas 1 127.0.0.1:6481 127.0.0.1:6482 127.0.0.1:6483 127.0.0.1:6484 127.0.0.1:6485 127.0.0.1:6486

出现提示创建3主3从集群的时候,输入yes即可。

3.6 脚本自动化

运维人员可以将脚本做一些完善,在linux下自动化创建安装redis节点,自动化创建集群

4 集群在线扩容

1)准备新节点

2) 加入集群 

3)迁移槽和数据

在生产环境可以用redis-trib.rb工具来做集群扩容,做到半自动化,建议运维人员在测试环境先摸透整个流程。


添加节点:

redis-trib.rb add-node 127.0.0.1:6385 127.0.0.1:6379 

迁移槽:

1、redis-trib.rb reshard 10.42.202.243:6000   #任意指定一个节点,以便获取集群信息

2、接下来要你输入需要迁移的槽数量 :2000

3、输入目标节点的nodeid

4、输入源节点的ID ,要是主节点的id,输入done表示结束

5、输入yes,开搞吧

6、为新增的主节点添加slave:

redis-trib.rb add-node --slave ip:port masterip:port

5 故障转移原理

5.1 集群内部通信

集群内部采用gossip协议进行通信,节点之间交换彼此的信息,使用了单独的TCP端口,默认是6379+10000。详细过程请阅读“redis开发与运维.PDF”


5.2 故障发现

当集群少量节点出行故障时,能通过自动化故障转移保证集群的高可用。那是怎么发现故障节点的呢?

包括两个环节:主观下线pfail (单个节点认为另一个节点下线,将它标记为pfail) 、客观下线 fail(节点彼此之间通过信息交换,大家达成共识了,都认为该节点下线,标记为fail)

这里所说的“大家达成共识了”,指的是主节点投票超过半数以上,就是说如果是3主3从集群,至少要有2个主节点认为该节点下线,从节点没资格参与投票。

如果是主节点,就要进行故障转移了

5.3 故障转移 

主节点发生故障了,从节点收到fail广播消息,从节点会尝试发起选举

其他主节点接收到选举消息,会进行投票,超过半数以上通过才可以完成选举。

(详细过程请阅读redis开发与运维.pdf)

故障主节点也算在投票数内,假设集群内节点规模是3主3从,其中有2 个主节点部署在一台机器上,当这台机器宕机时,由于从节点无法收集到 3/2+1个主节点选票将导致故障转移失败。这个问题也适用于故障发现环 节。因此部署集群时所有主节点最少需要部署在3台物理机上才能避免单点 问题。

6 集群运维注意事项

  在上线之前进行故障转移测试,及时发现问题,锻炼掌握集群运维能力

 学会从cpu  网络 存储 日志各个层面进行日常运维

6.1 常用命令

redis-cli -p 6000 -h host 

redis-cli -p 6000 shutdown

cluster nodes  

6.2 基准测试工具

redis-benchmark -h 11.4.74.44  -p 6000  -c 100 -n 20000

基准测试的数据由于key value  大小 网络因素等,并不能直接等同于生产环境的qps,但是可以做大致参考。

6.3 运维案例

用户报的一个故障:

org.redisson.client.RedisException: ERR max number of clients reached. channel: [id: 0x136f239c, L:/11.13.49.91:34666 - R:/11.4.74.47:6000] command: (READONLY), params: []

排查过程:首先确认内核配置无误

/etc/sysctl.conf  fs.file-max=65535

ulimit -n  最大文件描述符   65536

redis.conf配置:max clients 50000    timeout  0

使用redis-cli工具:info  clients查看当前客户端连接数  ,发现快占满了,接近5w,wtf这怎么可能。。

查看所有client:client list

查看timeout配置:config get timeout    0 ,这是问题根源之一

临时性设置timeout:config set timeout 150

monitor命令可以显示当前redis执行的命令,发现同一个ip有很多重复性的占用连接。

反查这些ip实例的日志,发现应用程序不能正常启动,一直重启,导致一直重复创建连接,又缺乏超时释放的策略

先干掉不能启动的几个应用实例。

解决方案:一定要设置redis.conf的timeout 60,不能让空闲连接占着茅坑不拉屎,把所有连接耗尽。容器一定要配置健康检查,如果发现反复重启的,要格外关注。

举一反三:rocketmq、kafka、es呢


7  针对开发人员

 7.1 熟悉redis架构原理

别拿他当黑盒用,了解哪些操作会导致redis阻塞。否则就是给自己挖坑

7.2 使用redisson 而不是jedis

很傻瓜化的一个java客户端,磨刀不误砍柴工,多查看官网api文档,如果你用的很辛苦,那可能是你的姿势不对

 7.3 redis使用规范

在实际生产环境中,不可能给每个应用都建一套redis集群,一般是按业务领域分。

为了防止key冲突,各个应用直接约定key值加上约定的前缀来区分。


7.4 批量设置

在cluster模式下,对mset  mget命令限制很多,要求批量设置的key 都在同一台redis实例上,否则报异常。

有什么替代方案呢?用hashmap

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容