50 个 Redis 必备知识:基础知识,架构、调优和监控知识及难点解决_java

本文包括:30 个 Redis 基础知识;10个 Redis 架构和运维必懂的知识;Redis 调优、监控知识和10个具体应用难点。

30 个 Redis 基础知识

1、Redis支持哪几种数据类型?

String、List、Set、Sorted Set、hashes

2、Redis主要消耗什么物理资源?

Redis是一种基于内存高性能的数据库--- 主要依赖于内存

3、Redis有哪几种数据淘汰策略?

noeviction:返回错误当内存限制达到并且客户端尝试执行会让更多内存被使用的命令(大部分的写入指令,但DEL和几个例外)

allkeys-lru:尝试回收最少使用的键(LRU),使得新添加的数据有空间存放。

volatile-lru:尝试回收最少使用的键(LRU),但仅限于在过期集合的键,使得新添加的数据有空间存放。

allkeys-random:回收随机的键使得新添加的数据有空间存放。

volatile-random:回收随机的键使得新添加的数据有空间存放,但仅限于在过期集合的键。

volatile-tt:回收在过期集合的键,并且优先回收存活时间(TTL)较短的键,使得新添加的数据有空间存放。

4、为什么Redis需要把所有数据放到内存中?

Redis为了达到最快的读写速度将数据都读到内存中,并通过异步的方式将数据写入磁盘。所以redis具有快速和数据持久化的特征。如果不将数据放在内存中,磁盘I/O速度为严重影响redis的性能。在内存越来越便宜的今天,redis将会越来越受欢迎。如果设置了最大使用的内存,则数据已有记录数达到内存限值后不能继续插入新值。

5、Redis集群方案应该怎么做?都有哪些方案?

1.twemproxy,大概概念是,它类似于一个代理方式,使用方法和普通redis无任何区别,设置好它下属的多个redis实例后,使用时在本需要连接redis的地方改为连接twemproxy,它会以一个代理的身份接收请求并使用一致性hash算法,将请求转接到具体redis,将结果再返回twemproxy。使用方式简便(相对redis只需修改连接端口),对旧项目扩展的首选。问题:twemproxy自身单端口实例的压力,使用一致性hash后,对redis节点数量改变时候的计算值的改变,数据无法自动移动到新的节点。

2.codis,目前用的最多的集群方案,基本和twemproxy一致的效果,但它支持在 节点数量改变情况下,旧节点数据可恢复到新hash节点。

3.redis cluster3.0自带的集群,特点在于他的分布式算法不是一致性hash,而是hash槽的概念,以及自身支持节点设置从节点。具体看官方文档介绍。

4.在业务代码层实现,起几个毫无关联的redis实例,在代码层,对key 进行hash计算,然后去对应的redis实例操作数据。这种方式对hash层代码要求比较高,考虑部分包括,节点失效后的替代算法方案,数据震荡后的自动脚本恢复,实例的监控,等等。

6、Redis集群方案什么情况下会导致整个集群不可用?

有A,B,C三个节点的集群,在没有复制模型的情况下,如果节点B失败了,那么整个集群就会以为缺少5501-11000这个范围的槽而不可用。

7、Redis如何设置密码及验证密码?

设置密码:config set requirepass 123456

授权密码:auth 123456

8、说说Redis哈希槽的概念?

Redis集群没有使用一致性hash,而是引入了哈希槽的概念,Redis集群有16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置哪个槽,集群的每个节点负责一部分hash槽。

9、Redis集群的主从复制模型是怎样的?

为了使在部分节点失败或者大部分节点无法通信的情况下集群仍然可用,所以集群使用了主从复制模型,每个节点都会有N-1个复制品.

10、Redis集群会有写操作丢失吗?为什么?

Redis并不能保证数据的强一致性,这意味着在实际中集群在特定的条件下可能会丢失写操作。

11、Redis集群之间是如何复制的?

异步复制

12、怎么理解Redis事务?

事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。

事务是一个原子操作:事务中的命令要么全部被执行,要么全部都不执行。

13、Redis事务相关的命令有哪几个?

MULTI、EXEC、DISCARD、WATCH

14、Redis key的过期时间和永久有效分别怎么设置?

EXPIRE和PERSIST命令。

15、Redis如何做内存优化?

尽可能使用散列表(hashes),散列表(是说散列表里面存储的数少)使用的内存非常小,所以你应该尽可能的将你的数据模型抽象到一个散列表里面。比如你的web系统中有一个用户对象,不要为这个用户的名称,姓氏,邮箱,密码设置单独的key,而是应该把这个用户的所有信息存储到一张散列表里面.

16、Redis回收进程如何工作的?

一个客户端运行了新的命令,添加了新的数据。

Redi检查内存使用情况,如果大于maxmemory的限制, 则根据设定好的策略进行回收。

一个新的命令被执行,等等。

所以我们不断地穿越内存限制的边界,通过不断达到边界然后不断地回收回到边界以下。

如果一个命令的结果导致大量内存被使用(例如很大的集合的交集保存到一个新的键),不用多久内存限制就会被这个内存使用量超越。

17、Redis回收使用的是什么算法?

LRU算法

18、Redis如何做大量数据插入?

Redis2.6开始redis-cli支持一种新的被称之为pipe mode的新模式用于执行大量数据插入工作。

19、为什么要做Redis分区?

分区可以让Redis管理更大的内存,Redis将可以使用所有机器的内存。如果没有分区,你最多只能使用一台机器的内存。分区使Redis的计算能力通过简单地增加计算机得到成倍提升,Redis的网络带宽也会随着计算机和网卡的增加而成倍增长。

20、Redis持久化数据和缓存怎么做扩容?

如果Redis被当做缓存使用,使用一致性哈希实现动态扩容缩容。

如果Redis被当做一个持久化存储使用,必须使用固定的keys-to-nodes映射关系,节点的数量一旦确定不能变化。否则的话(即Redis节点需要动态变化的情况),必须使用可以在运行时进行数据再平衡的一套系统,而当前只有Redis集群可以做到这样。

21、分布式Redis是前期做还是后期规模上来了再做好?为什么?

既然Redis是如此的轻量(单实例只使用1M内存),为防止以后的扩容,最好的办法就是一开始就启动较多实例。即便你只有一台服务器,你也可以一开始就让Redis以分布式的方式运行,使用分区,在同一台服务器上启动多个实例。

一开始就多设置几个Redis实例,例如32或者64个实例,对大多数用户来说这操作起来可能比较麻烦,但是从长久来看做这点牺牲是值得的。

这样的话,当你的数据不断增长,需要更多的Redis服务器时,你需要做的就是仅仅将Redis实例从一台服务迁移到另外一台服务器而已(而不用考虑重新分区的问题)。一旦你添加了另一台服务器,你需要将你一半的Redis实例从第一台机器迁移到第二台机器。

22、都有哪些办法可以降低Redis的内存使用情况呢?

如果你使用的是32位的Redis实例,可以好好利用Hash,list,sorted set,set等集合类型数据,因为通常情况下很多小的Key-Value可以用更紧凑的方式存放到一起。

23、查看Redis使用情况及状态信息用什么命令?

info

24、Redis的内存用完了会发生什么?

如果达到设置的上限,Redis的写命令会返回错误信息(但是读命令还可以正常返回。)或者你可以将Redis当缓存来使用配置淘汰机制,当Redis达到内存上限时会冲刷掉旧的内容。

25、Redis是单线程的,如何提高多核CPU的利用率?

可以在同一个服务器部署多个Redis的实例,并把他们当作不同的服务器来使用,在某些时候,无论如何一个服务器是不够的, 所以,如果你想使用多个CPU,你可以考虑一下分片(shard)。

26、一个Redis实例最多能存放多少的keys?List、Set、Sorted Set他们最多能存放多少元素?

理论上Redis可以处理多达232的keys,并且在实际中进行了测试,每个实例至少存放了2亿5千万的keys。我们正在测试一些较大的值。

任何list、set、和sorted set都可以放232个元素。

换句话说,Redis的存储极限是系统中的可用内存值。

27、Redis常见性能问题和解决方案?

(1) Master最好不要做任何持久化工作,如RDB内存快照和AOF日志文件

(2) 如果数据比较重要,某个Slave开启AOF备份数据,策略设置为每秒同步一次

(3) 为了主从复制的速度和连接的稳定性,Master和Slave最好在同一个局域网内

(4) 尽量避免在压力很大的主库上增加从库

(5) 主从复制不要用图状结构,用单向链表结构更为稳定,即:Master <- Slave1 <- Slave2 <- Slave3...

这样的结构方便解决单点故障问题,实现Slave对Master的替换。如果Master挂了,可以立刻启用Slave1做Master,其他不变。

28、Redis提供了哪几种持久化方式?

RDB持久化方式能够在指定的时间间隔能对你的数据进行快照存储。

AOF持久化方式记录每次对服务器写的操作,当服务器重启的时候会重新执行这些命令来恢复原始的数据,AOF命令以redis协议追加保存每次写的操作到文件末尾。Redis还能对AOF文件进行后台重写,使得AOF文件的体积不至于过大。

如果你只希望你的数据在服务器运行的时候存在,你也可以不使用任何持久化方式。

你也可以同时开启两种持久化方式,在这种情况下,当redis重启的时候会优先载入AOF文件来恢复原始的数据,因为在通常情况下AOF文件保存的数据集要比RDB文件保存的数据集要完整。

最重要的事情是了解RDB和AOF持久化方式的不同,让我们以RDB持久化方式开始。

29、如何选择合适的持久化方式?

一般来说, 如果想达到足以媲美PostgreSQL的数据安全性, 你应该同时使用两种持久化功能。如果你非常关心你的数据, 但仍然可以承受数分钟以内的数据丢失,那么你可以只使用RDB持久化。

有很多用户都只使用AOF持久化,但并不推荐这种方式:因为定时生成RDB快照(snapshot)非常便于进行数据库备份, 并且 RDB 恢复数据集的速度也要比AOF恢复的速度要快,除此之外, 使用RDB还可以避免之前提到的AOF程序的bug。

30、修改配置不重启Redis会实时生效吗?

针对运行实例,有许多配置选项可以通过 CONFIG SET 命令进行修改,而无需执行任何形式的重启。从 Redis 2.2 开始,可以从 AOF 切换到 RDB 的快照持久性或其他方式而不需要重启 Redis。检索 ‘CONFIG GET *’ 命令获取更多信息。

但偶尔重新启动是必须的,如为升级 Redis 程序到新的版本,或者当你需要修改某些目前 CONFIG 命令还不支持的配置参数的时候。

(以上内容来自“Java核心技术”,作者:不羁码农 )


10个 Redis 架构和运维必懂的知识

(以下内容来自社区交流整理,有些问题可能有多个解读)


一、高可用相关

1、Redis 常用高可用架构有哪些?

Redis 高可用架构如下:

  • Redis Sentinel 集群 + 内网 DNS + 自定义脚本
  • Redis Sentinel 集群 + VIP + 自定义脚本
  • 封装客户端直连 Redis Sentinel 端口
    • JedisSentinelPool,适合 Java
    • PHP 基于 phpredis 自行封装
  • Redis Sentinel 集群 + Keepalived/Haproxy
  • Redis M/S + Keepalived
  • Redis Cluster
  • Twemproxy
  • Codis

2、Redis 高可用架构优劣对比?

—Redis Sentinel 集群 + 内网 DNS + 自定义脚本

优点:

  • 秒级切换
  • 脚本自定义,架构可控
  • 对应用透明

缺点:

  • 维护成本略高
  • 依赖 DNS,存在解析延时
  • Sentinel 模式存在短时间的服务不可用

—Redis Sentinel 集群 + VIP + 自定义脚本

优点:

  • 秒级切换
  • 脚本自定义,架构可控
  • 对应用透明

缺点:

  • 维护成本略高
  • Sentinel 模式存在短时间的服务不可用

—封装客户端直连 Redis Sentinel 端口

优点:

  • 服务探测故障及时
  • DBA 维护成本低

缺点:

  • 依赖客户端支持 Sentinel
  • Sentinel 服务器需要开放访问权限
  • 对应用有侵入性

—Redis Sentinel 集群 + Keepalived/Haproxy

优点:

  • 秒级切换
  • 对应用透明

缺点:

  • 维护成本高
  • 存在脑裂
  • Sentinel 模式存在短时间的服务不可用

—Redis M/S +Keepalived

优点:

  • 秒级切换
  • 对应用透明
  • 部署简单,维护成本低

缺点:

  • 需要脚本实现切换功能
  • 存在脑裂

(Redis Cluster、Twemproxy、Codis 优劣对比见下个问题)

3、常见的 Redis 集群方案有哪些优缺点?

Twemproxy:

50 个 Redis 必备知识:基础知识,架构、调优和监控知识及难点解决_java_02

多个同构 Twemproxy(配置相同)同时工作,接受客户端的请求,根据 hash 算法,转发给对应的 Redis。

优点:

  • 开发简单,对应用几乎透明
  • 历史悠久,方案成熟

缺点:

  • 代理影响性能
  • LVS 和 Twemproxy 会有节点性能瓶颈
  • Redis 扩容非常麻烦
  • Twitter 内部已放弃使用该方案,新使用的架构未开源

Codis:

50 个 Redis 必备知识:基础知识,架构、调优和监控知识及难点解决_java_03

  • ZooKeeper
    • 存放路由表和代理节点元数据
    • 分发Codis-Config的命令
  • Codis-Config 集成管理工具,有web界面
  • Codis-Proxy
    • 无状态代理,兼容Redis协议
    • 对业务透明
  • Codis-Redis
    • 基于2.8版本,二次开发
    • 加入slot支持和迁移命令

优点:

  • 开发简单,对应用几乎透明
  • 性能比 Twemproxy 好
  • 有图形化界面,扩容容易,运维方便

缺点:

  • 代理依旧影响性能
  • 组件过多,需要很多机器资源
  • 修改了 Redis 代码,导致和官方无法同步,新特性跟进缓慢
  • 开发团队准备主推基于 Redis 改造的 reborndb

Redis Cluster:

50 个 Redis 必备知识:基础知识,架构、调优和监控知识及难点解决_java_04


P2P模式,无中心化。把 key 分成 16384 个 slot,每个实例负责一部分 slot。客户端请求若不在连接的实例,该实例会转发给对应的实例。通过Gossip协议同步节点信息。

优点:

  • 组件 all-in-box,部署简单,节约机器资源
  • 性能比 proxy 模式好
  • 自动故障转移、Slot 迁移中数据可用
  • 官方原生集群方案,更新与支持有保障

缺点:

  • 架构比较新,最佳实践较少
  • 多键操作支持有限(驱动可以曲线救国)
  • 为了性能提升,客户端需要缓存路由表信息
  • 节点发现、reshard 操作不够自动化

二、Redis 通用

1、Redis 相对 MySQL、PostgreSQL 这些关系型数据库,有什么优缺点?

观点一:

Redis 主要是用来做缓存,它有持久化,但也只是为了缓存的可靠而已。优点是数据全放内存,速度快。缺点就是,数据大小不能超过内存大小。两个用在不同业务场景,Redis 无法取代传统关系型数据库。

观点二:

Redis 首先它是一种内存数据库,最大的优势在于效率高。尤其在某些特定场合下,例如热点数据量非常大,而数据从内存和磁盘之间的换入换出代价比较高的情况下,Redis 就会体现它的价值。

传统关系型数据库在于它对数据的一致性保障,它的数据模型范式是遵循严格事务规则的结构化数据,由于其数据的高度抽象化,它调度到内存的数据一般场合下不会占用很大的内存空间。

总的来说,两种数据库各有各的优点和缺点。不同的业务场合有特定的追求目标,redis 首要的是效率,适用的是一些单纯二维结构化数据无法表达的数据模型,而关系型数据库处理的是可以用范式模型表达的二维数据,追求的是数据的高度一致性。随着 IT 的发展,每一类型的数据库都会在其特定的场合内发挥出无可比拟的优势,最终的趋势是大家趋于平衡,没有最好,只有最适合。

观点三:

记住一句话:任何数据库都有自己的应用场景,应该关注数据流、数据属性。

个人的经验来说,Redis 不可能取代 MySQL 或者 PG。

2、Redis 有哪些应用场景?

Redis 是一个高性能的缓存,一般应用在 Session 缓存、队列、排行榜、计数器、最近最热文章、最近最热评论、发布订阅等。

更多应用场景,可以参考此处。

可以这样讲,Redis 适用于 数据实时性要求高、数据存储有过期和淘汰特征的、不需要持久化或者只需要保证弱一致性、逻辑简单的场景。

3、新接手一个复杂的 Redis 集群(Sentinel 模式),如何了解它

刚刚接手一套 Redis 集群,想要了解这套集群的相关配置。应该如何入手。难道只能通过 info 命令去查看各个配置吗?

这是笔者的建议:

  • 通读 Sentinel 官方文档:https://redis.io/topics/sentinel
  • Google 搜索 Redis Sentinel,找几篇中英文的文章看看
  • 进入 Sentinel 集群后,使用 info 查看集群信息
  • 查看 Sentinel 配置文件,配合文档搞清楚每个参数的含义
  • 使用几台虚拟机模拟线上环境,然后做测试,在实践中深入理解
  • 思考当前 Sentinel 集群是否有不合理的地方,如有,提出并改进

三、Redis 故障排查

1、Redis 实例中,存在大量的 FIN_WAIT2 连接

客户端 TCP 状态迁移:

CLOSED->SYN_SENT->ESTABLISHED->FIN_WAIT_1->FIN_WAIT_2->TIME_WAIT->CLOSED

服务器 TCP 状态迁移:

CLOSED->LISTEN->SYN 收到 ->ESTABLISHED->CLOSE_WAIT->LAST_ACK->CLOSED

这个状态存在于主动发起断开请求的一端,如果服务器存在大量的这个状态,那么这个服务器就充当客户端的角色,如网络爬虫,出现的原因是由于客户端发起 FIN 请求结束连接之后,收到了服务端的应答之后进入 FIN_WAIT2,之后就没收到服务端发送的 FIN 信号导致。

PS:线上 Web 客户端用的什么语言?

此问题的评论值得一看:http://www.aixchina.net/Question/231035-1406575

2、如何知道当前 Redis 实例是处于阻塞状态?

解答一:

随便 get 一个 key,然后卡着不动就行,简单粗暴。优雅一点是看 latency 的延迟,blocked_clients 的数量,rejected_connections 的数量等。

解答二:

  • 方法一:登录 Redis,执行 info,查看 blocked_clients
  • 方法二:执行 redis-cli --latency -h -p 查看延时情况

3、Redis 运维的故障有哪些?

回答一:

常见的运维故障

  • 使用 keys * 把库堵死,——建议使用别名把这个命令改名
  • 超过内存使用后,部分数据被删除——这个有删除策略的,选择适合自己的即可
  • 没开持久化,却重启了实例,数据全掉——记得非缓存的信息需要打开持久化
  • RDB 的持久化需要 vm.overcommit_memory=1,否则会持久化失败
  • 没有持久化情况下,主从,主重启太快,从还没认为主挂的情况下,从会清空自己的数据——人为重启主节点前,先关闭从节点的同步

回答二:

我简单说下 Redis 故障的排查方法吧。

  • 了解清楚业务数据流是怎么样的
  • 结合 Redis 监控查看 QPS、缓存命中率、内存使用率等信息
  • 确认机器层面的资源是否有异常
  • 故障时及时上机,使用 redis-cli monitor 打印出操作日志,然后分析(事后分析此条失效)
  • 和研发沟通,确认是否有大 Key 在堵塞(大 Key 也可以在日常的巡检中获得)
  • 和组内同事沟通,确实是否有误操作
  • 和运维同事、研发一起排查流量是否正常,是否存在被刷的情况

更多的排查需要对线上系统的分析。

四、Redis 性能优化

1、提高 Redis 内存数据库的性能,有哪些措施?

这个问题有点偏题了,还是回答下吧。整理下工作中积累的经验:

  • 根据不同业务选择数据类型,有必要时对数据结构进行审核,减少数据冗余
  • 精简键名和键值,控制键值的大小
  • 使用前缀管理好 key
  • 使用 scan 代替 keys,将遍历 Redis DB 中所有 key 的操作放到客户端来做
  • 避免使用 O(N) 复杂度的命令
  • 配置使用 ziplist 来优化 list
  • 合理配置 maxmemory
  • 数据量大的情况,做好 key 和 value 的压缩
  • 利用管道,批量处理命令
  • 根据不同业务选择短链接或者长链接
  • 定期使用 redis-cli --big-keys 检测大 Key

(以上内容由温国兵、liucj2004、赵海等社区专家和会员分享,温国兵整理汇编。)


Redis 调优、监控知识和10个具体应用难点


一、Redis数据库的优缺点及适用场景

Redis持久服务的特点,key-value键值类型存储系统,支持数据可靠存储,单进程单线程高性能服务器,恢复比较慢单机qps(秒并发)可以达到10W,适合小数据高速读写访问。

Redis存储系统优、缺点:可以持久化存储数据,支持每秒10W的读写频率,支持丰富的数据类型,所有操作都是原子性的,支持异机主从复制,内存管理开销大(低于物理内存的3/5),不同命令延迟差别大,官方网站:http://www.redis.io

主要使用场景分为两大块:

1、缓存:热点数据放到缓存里,大部分情况命中缓存,不命中时,访问磁盘存储并更新缓存

2、键值存储,独立使用缓存作为数据提供方。依赖于缓存服务的可靠性不高,业务对事务和数据的一致性要求不高。具体的,一般由架构师和开发人员,根据业务的特性,设计出具体的使用方法。

二、Redis的调优参数

Redis的参数调优问题,根据场景不同,有不同的调优方法,以下列举踩过的一些坑的参数调优。我们的场景的海量数据,高并发。

(1)timeout参数,非常需要关注,官方对timeout的解释如下:该参数表示当某一个客户端连接上来并闲置timeout(单位秒)的时间后,Redis服务端就主动关闭这个客户端连接。我们发现如果客户端对连接处理比较差的时候,存在连接不释放的问题,导致连接池耗尽,单个redis默认的连接数是1000.所以需要在timeout参数做文章,强制释放无效连接,我们的参数调整为timeout 30000

(2)持久化参数,RDB和AOF究竟开哪个,很多人很纠结。其实选择很简单,两者的区别是持久化的颗粒度不一样,如果你关注数据的强一致性,选择AOF,如果你选择更好的性能,选型RDB。如果你选择极致的性能,又能容忍数据的丢失,那你可以完全不用开启持久化,当然了,集群是一定要开持久化的。

(3)tcp-backlog和maxclient,这两个参数可能大家也比较迷糊,maxclient模式10000,一般情况下是够了,但是在高并发海量访问的时候,还是会出现客户端缓慢的情况,那就是系统的限制,就是backlog参数,你可以理解为在三次握手时进入accept queue队列的最大值,也就是send_Q,所以这个值设大点是没有坏处的,我们的设置是1024

(4)重点提一下安全的参数,requirepass foobared 个人认为,如果你们觉得你们hold住,那就不用开,如果在DMZ区,数据又比较重要,那就开。个人认为,密码的作用不是你想象中的带给你安全,第一redis一分钟可以访问你想象不到的次数,如果弱密码,分分钟破解,第二auth命令是明文的,破解也很容易。

(5)maxmemory,这个参数比较常见,但是也非常的坑。如果你选择用,有个原则,你是当数据库用还是当缓存用,如果当数据库用,就不要开,如果当缓存用,可以开。曾经有个BUG,多个salve的情况下,会导致擦除主节点的数据。如果你开启这个参数,记得预留一些空间给系统的buffer。

遵循你的使用场景和你对参数的了解。宁愿逐步踩坑逐步解决问题逐步深入了解,也不要盲从的调整参数。

三、Redis 的监控指标

内存使用。如果 Redis 使用的内存超出了可用的物理内存大小,那么 Redis 很可能系统会被杀掉。针对这一点,你可以通过 info 命令对 used_memory 和 used_memory_peak 进行监控,为使用内存量设定阀值,并设定相应的报警机制。当然,报警只是手段,重要的是你得预先计划好,当内存使用量过大后,你应该做些什么,是清除一些没用的冷数据,还是把 Redis 迁移到更强大的机器上去。

持久化。如果因为你的机器或 Redis 本身的问题导致 Redis 崩溃了,那么你唯一的救命稻草可能就是 dump 出来的rdb文件了,所以,对 Redis dump 文件进行监控也是很重要的。可以通过对rdb_last_save_time 进行监控,了解最近一次 dump 数据操作的时间,还可以通过对rdb_changes_since_last_save进行监控来获得如果这时候出现故障,会丢失(即已改变)多少数据。

Keys。通过获取Keyspace中的结果得到各个数据库中key的数量

QPS。即每分钟执行的命令个数,即:(total_commands_processed2-total_commands_processed1)/span,为了实时得到QPS,可以设定脚本在后台运行,记录过去几分钟的total_commands_processed。在计算QPS时,利用过去的信息和当前的信息得出QPS的估计值。

四、如何更好更合理的使用Redis——10个具体应用难点解读

1.Redis与Oracle中存有同一份数据,当数据发生变化时,应用程序是先写Redis然后再同步到Oracle,还是先写Oracle然后再同步到Redis呢,使用何种同步机制可以有效的解决这个时间差中两份数据的不一致性呢?

答:如果你是当数据库用,那就类似于电商抢购场景。抢购的场景中有个需要解决的问题是超买和超卖,意思就是说,我要控制库存数量,而且要保证可用库存的数量为0,不能出现负数。一般是把数据从Oracle刷到Redis,贴合题主的问题,那就是同样有一份数据,当数据变化的时候,是先写Redis还是先写Oracle?是先写Redis,再写Oracle,因为代码层面保证数据的一致性,在高并发情况下,悲观锁机制并不会很友好,而且影响性能。而redis天然的原子性事务,是可以保证数据的一致性。

如果你当缓存用,又要确保数据的强一致性,是可以先写Redis,也可以先写Oracle,如果先写Redis,参考前一段话,采取Redis的强一致性;如果先写Oracle,那就采取悲观锁来实现。

2.目前的监控系统是Python到Oracle取配置信息,经过运算之后再写回Oracle,然后根据阀值来触发告警,在这样的模式之下Redis是否有可以应用的空间呢?

答:当你的监控的需求具备秒级监控的能力后,你的web-db的架构就不再满足了
比如说以下场景

1:基于日志的流式计算

2:监控指标的基线

3:数据的统计分析

4:通用的计算周期

5:多维度的告警规则:如无数据告警、基于同环比的告警、基于基线的告警、

越来越多的监控场景、监控指标、触发器,redis的作用就是提供你更快、更优质的服务

3.我们的系统现在使用了两套Redis;分别用作热点数据缓存、会话保持保存全局ID。热点数据缓存采用的是一主一从三哨兵(分别独立,共五个节点);会话保持采用的是一主三从四个哨兵(共四个节点,每个节点上启动了一个哨兵进程);这个是乙方给的方案,请教大神,这个方案可靠吗?能否使用cluster方案来替代呢?有必要吗?

答:你有两套Redis,A作为热数据缓存,B作为回话保持。

缺点:A有5个节点,B有4个节点,9个节点中只有2个节点是主节点,提供服务,备节点只是冗余,存在比较大的资源浪费。

优点:sentinel集群,客户端可以随意地连接任意一个sentinel来获得关于redis集群中的信息,做到代理层的可用性。切换至cluster后在资源使用率方面,按照9节点的规模,实际组网只能有8台,4主4从,资源使用率得到很大的提升,而且代理层分别由8个节点负担,因此,也能保证了可用性。

4.主机房部署了Redis集群,并数据持久化。问题:要求在主机房发生灾难并不可修复的情况下,容灾机房能在一定时间内承担起主机房的业务能力。如何保障容灾机房的Redis集群数据跟主机房一致?如何操作??

答:主要看你采用集群的方式,如果是cluster,请参考,关于双活机房中cluster模式的组网,根据你的业务场景来决定。如果redis的使用中并不处在核心链路上,完全当做cache来使用,且在击穿情况下有后续的数据库来支撑,可以放在同一机房内。如果Redis的使用在核心链路上,当做数据库来使用,在单侧机房部署,不能保证多机房环境下的多活。以双活机房为例,集群有A、a、B、b、C、c节点,A、B、C三个节点部署在甲机房,a、b、c三个节点部署在乙机房,甲乙两个机房使用波分线路进行大二层透传,能够使某一业务同时在某一都使用同一网段地址。基于Redis本身,能够实现双数据副本模式,当甲机房单侧异常时,乙机房单侧接管,重新完成组网,提供服务。

如果是其他集群,请描述,我再补充。我大概明白你的意思了,我猜测1:你应该没有使用集群模式,而且采取了无状态的三个节点,进行组网。2:你采取的cluster,三主三从都是部署在单侧机房。目前你的做法是AB两个机房,你集群部署在A单侧机房,另外在B机房又复制了A机房的集群镜像,当单侧机房故障时,B机的Redis进行启动进行加载数据提供服务。目前我有个问题,你们有没有演练过?且应用要不要改Redis的IP?如果你们对Redis的场景没有横向扩展的要求,建议在Redis集群上加一层代理,比如sentinel、twemproxy通过代理去路由Redis,同时Redis的主备分别部署两侧机房,当主节点异常,备节点进行选举接管。

5.多个系统共用Redis集群,如何防止某个系统独占大量资源,导致其他系统不可用?

答:多个系统共用一套redis的前提,那就是不能对其他业务有影响。1:key-value的命名规范、2:定义使用场景、3:完善的监控、4:定期巡检慢查询日志

6.Redis生产部署中集群方案是否有简化部署?

目前,在实际生产部署中,已经在使用Redis主备方案的部署,但还仅是依靠硬件负载均衡设备进行应用分发后,由2台Redis服务器实现主备。基于Redis在系统仅是做为数据写入缓存的单一功能。想了解一下除了Redis多机集群,是否有简单的Redis双机部署方案,性能如何?(2台物理机,我们是电力行业系统 ,用于将通信端抄送上来的并发数20万左右的报文缓存,然后存于数据库!)

答:20万的数据量不大,可以采用Redis主从方式,搭配sentinel进行自动主从切换。如果团队开发能力较强,可以研究一下twemproxy开源架构。另外,Redis是单线程模式运行的,为了充分使用机器的CPU资源,可以搭建多个Redis实例,部署多套主从架构,或者使用twemproxy开源架构对数据进行分片,适应将来的业务量上涨。

7.Redis cluster在多活机房中采取怎样的架构?

答:关于双活机房中cluster模式的组网,根据你的业务场景来决定。

如果Redis的使用中并不处在核心链路上,完全当做cache来使用,且在击穿情况下有后续的数据库来支撑,可以放在同一机房内。如果Redis的使用在核心链路上,当做数据库来使用,在单侧机房部署,不能保证多机房环境下的多活。以双活机房为例,集群有A、a、B、b、C、c节点,A、B、C三个节点部署在甲机房,a、b、c三个节点部署在乙机房,甲乙两个机房使用波分线路进行大二层透传,能够使某一业务同时在某一都使用同一网段地址。基于Redis本身,能够实现双数据副本模式,当甲机房单侧异常时,乙机房单侧接管,重新完成组网,提供服务。

8.Redis Cluster什么情况下会导致数据丢失,应该怎么避免?

答:cluster模式下数据丢失,有两种可能1:请求击穿,写入失败,这个要从代码层面来解决;2:主从切换,从节点的数据跟主节点数据有差异。这个解决方式可以采取配置always参数,保持数据的大概率的一致性。

9.Redis主从间是异步复制,这里提到强一致是如何做到的?应用层的工作吗?

答:不得不说,Redis的数据同步,强一致性是有前置条件的,强一致性的根据有两个前提,1:持久化文件的生成的一致性;2:持久化文件的写入的一致性。针对1,目前有两种持久化方式,RDB和AOF,针对两者而言,其实都是异步的,两个都有优缺点,但针对落地数据而言,都是异步的,所以能做到准实时,不能做到真正意义上的实时。很多人有疑问了,appendfsync always这个参数明明是同步的,是能牺牲性能保证数据的一致性的。仔细看官网的介绍,AOF持久化中的文件写入操作其实是将aof_buf缓冲区的内容存放到了内存缓冲区中,这时还没有真正写入到磁盘中,这个缓冲区达到同步条件时,才会执行fsync将这个缓冲区的内容写入到硬盘中,完成文件同步。所以持久化和REDIS事务的原子性是解耦的。针对2,取决于持久化文件的大小,曾遇到一种情况,当持久化文件非常大的时候,同步也是需要时间的。综上所述,不能做到绝对的强一致性,只能做到可接受的范围的强一致性。

10.在金融行业,为了保证数据的强一致性,应该选择哪种持久化方式?换句话说,在主从切换中,通过哪些途径保持数据的强一致性?

答:持久化并且要保证数据不丢失:可以开启aof备份,并且把appendfsync参数设置为 always ,保证收到写命令后就立即写入磁盘,但是效率最差,一般的sata盘只能支持几百的QPS。可以使用高效的SSD磁盘提升性能。但是这也违背了redis高速缓存的初衷。主从切换:目前原生redis不支持同步复制,它的主从只能是异步复制,也就是无法保证数据强一致性。有些公司通过修改复制内核支持主从完全同步的复制。这也牺牲了性能和QPS。redis出现的目的是为了作为缓存提升访问性能,对数据一致性的支持相对比较弱。

(以上内容由社区专家顾黄亮总结整理)


原作者:顾黄亮总结整理
原文链接:50 个 Redis 必备知识:基础知识,架构、调优和监控知识及难点解决
原出处:twt企业IT社区
侵删

50 个 Redis 必备知识:基础知识,架构、调优和监控知识及难点解决_java_05