1 概要介绍
1.1 应用场景
缓存:相对静态、或变化缓慢的数据,可以利用缓存降低数据库IO压力,提升性能
分布式锁:集群环境下对同一个资源的竞争,可借助redis来实现对资源加锁。可查阅官方redlock相关介绍
秒杀:在redis中进行预处理,充当缓冲,将处理结果延迟持久化到数据库。规避高并发对DB的压力
计算器:每次操作加1,redis天然支持计数的api操作
消息队列:功能太简单,一般不用
分布式session
限数:每60秒获取一次验证码,设置key、value、失效时间1分钟到redis,每次获取校验码进行先验证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消耗。
2 架构原理
redis官方集群模式包括:单节点、一主一从,一主多从、哨兵模式、cluster模式等。开源方案codis实现的代理模式等等。
其他模式的优缺点这里就不讲了,这里讲讲cluster模式的优点:
高性能:客户端直连模式,没有代理转发。redis自身处理客户端请求飞快,纳秒级别
高并发:普通的硬件配置,单节点可支持60000QPS
高可用:单个主节点宕机不影响整体集群的服务能力,可通过自动健康检查、故障转移将从节点升级为主节点
可弹性扩展:在线水平扩展数据容量、吞吐量、主从节点个数等
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 内存剔除策略
3.2 注意事项
操作系统本身的最大连接数设置open files建议设置为65535,redis的最大连接数受此限制。
主节点平均分配到不同的机器上,否则容易造成单点故障以及复制风暴。
操作系统关闭THP
slave-read-only集群模式下无效,cluster集群模式下,从节点默认是处于冷备的状态,不提供读写服务。需要客户端去开启从节点的readonly,推荐用redisson java客户端工具,jedis不支持。
redis总共16个数据库,默认使用第0个数据库,集群模式下只能用第0数据库。多数据库功能就算单节点部署方案也不建议使用,这点知道即可。
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
编译安装:make installRedis编辑安装之后,src和/usr/local/bin目录下多了几个以redis开头可执行文 件
启动redis: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/data/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
./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
gem list --check redis gem
---安装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工具来做集群扩容,做到半自动化,建议运维人员在测试环境先摸透整个流程。
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 集群运维注意事项
6.1 在上线之前进行故障转移测试,及时发现问题,锻炼掌握集群运维能力
6.2 学会从cpu 网络 存储 日志各个层面进行日常运维
6.3 redis内存检测
redis-server --test-memory 1024
6.4 基准测试工具
redis-benchmark -h 11.4.74.44 -p 6000 -c 100 -n 20000
7 针对开发人员
7.1 熟悉redis架构原理
别拿他当黑盒用,了解哪些操作会导致redis阻塞。否则就是给自己挖坑
7.2 使用redisson 而不是jedis
很傻瓜化的一个java客户端,磨刀不误砍柴工,多查看官网api文档,如果你用的很辛苦,那可能是你的姿势不对
7.3 redis使用规范
在实际生产环境中,不可能给每个应用都建一套redis集群,一般是按业务领域分。
为了防止key冲突,各个应用直接约定key值加上约定的前缀来区分。
7.4 防爬虫的一些策略
请求透过缓存层,直接命中DB,并发量大,造成DB层宕机
造成缓存穿透的基本原因有两个。第一,自身业务代码或者数据出现问 题,第二,一些恶意攻击、爬虫等造成大量空命中。 解决方案:在redis中保存失效期较短的空缓存。
7.5 批量设置
在cluster模式下,对mset mget命令限制很多,要求批量设置的key 都在同一台redis实例上,否则报异常。
有什么替代方案呢?用hashmap
网友评论