如何理解分片数与副本数?
什么是分片
分片也叫 条带 ,指Redis集群的一个管理组,对应一个redis-server进程。一个Redis集群由若干条带组成,每个条带负责若干个slot(槽),数据分布式存储在slot中。Redis集群通过条带化分区,实现超大容量存储以及并发连接数提升。
每个集群实例由多个分片组成,每个分片默认为一个双副本的主备实例。分片数等于实例中主节点的个数。
什么是副本
副本指缓存实例的 节点 ,包含主节点和备节点。单副本表示实例没有备节点,双副本表示实例有备节点(一个主节点,一个备节点)。例如主备实例的副本数设置为3时,表示该实例有1个主节点,2个备节点。
不同实例类型的副本和分片数
- 单机实例: 单机实例只有1个节点,1个Redis进程,当Redis进程故障后,DCS为实例重新拉起一个新的Redis进程。
- 主备/读写分离实例: 分片数为1,包含一个主节点,一个或多个备节点。当主节点出现故障时,会进行主备倒换,恢复业务。副本数(备节点)越多,保障性更强,对实例的性能没有影响。
- 集群实例: 集群实例由多个分片组成,每个分片默认是一个双副本的主备实例。例如一个3分片,3副本的集群实例,则每个分片都有3个节点(个1主节点,2个备节点)。
实例类型 | 分片数 | 副本数 | 负载均衡 | 占用IP数 |
---|---|---|---|---|
单机 | 单分片 | - | - | 1个 |
主备 | 单分片 | 默认双副本,支持多副本 | 不支持 | 占用IP个数=副本数 |
读写分离 | 单分片 | 默认双副本,支持多副本 | 支持 | 1个 |
Proxy集群 | 多分片 | 双副本,不支持其他副本数 | 支持 | 1个 |
Cluster集群 | 多分片 | 默认双模本,支持单副本或多副本 | 不支持 | 占用IP个数=副本数*分片数 |
Redis实例CPU使用率达到100%的原因
- 可能原因1:
客户的业务负载过重,QPS过高,导致CPU被用满。
- 可能原因2:
使用了keys等消耗资源的命令。这会导致CPU使用率超高,容易触发主备倒换。
- 可能原因3:
发生Redis的持久化重写操作,CPU使用率增加。
详情请参考Redis实例CPU使用率高问题排查和解决。
Redis实例能否修改VPC和子网?
实例的VPC和子网,创建后不允许修改。如果要修改,请重新创建实例,在创建时选择指定的VPC和子网。如果实例已有数据需要迁移,可在创建实例之后,使用数据迁移进行迁移。
Redis 4.0/5.0/6.0实例为什么没有安全组信息?
目前Redis4.0/5.0/6.0版本实例是基于VPCEndpoint,暂不支持安全组,支持白名单配置。
如果需要指定的IP地址才能访问Redis实例,您需要将指定的IP地址加入到实例白名单中。
如果实例没有添加任何白名单或停用白名单功能,所有与实例所在VPC互通的IP地址都可以访问该实例。
Redis实例支持的单个Key和Value数据大小是否有限制?
- Key的大小上限为512M。
建议key的大小不超过1kb,这样既节约存储空间,也利于Redis进行检索。
- String类型的value值上限为512M。
- 集合、链表、哈希等key类型,单个元素的value上限为512M。
事实上,集合、链表、哈希都可以看成由String类型的key按照一定的映射关系组合而成。
同时,请注意避免对大Value进行长时间高并发写入,这样会影响网络传输效率,也会增加redis-server的内部处理耗时,从而导致请求时延较大。
Redis集群可以读取每个节点的IP地址吗?
Redis 3.0版本的集群实例(Proxy版本)的使用方式与单机、主备实例相同,无需知晓后端地址。
Redis 4.0及以上版本的集群实例(Cluster版本)可以使用cluster nodes命令获取。
redis-cli -h {redis_address} -p {redis_port} -a {redis_password} cluster nodes
在命令返回的结果中,获取所有master节点的IP端口,如下如所示:
创建缓存实例,为什么可使用内存比实例规格少一些?
Redis3.0版本采用虚拟机部署,系统会占用小部分内存。其他版本实例不存在该问题。
Redis实例是否支持读写分离?
Redis实例支持读写分离的情况如下表所示:
实例类型 | 是否支持读写分离 |
---|---|
读写分离实例 | 支持。说明读写分离功能,推荐使用读写分离实例 ,无需在客户端做任何配置。 |
Redis Cluster集群实例 | 支持从客户端实现读写分离,需要在客户端做配置,参考配置说明。 |
Redis 4.0/5.0/6.0主备实例 | 支持从客户端实现读写分离,需要在客户端增加用户读写请求判断。 |
其他版本及实例类型 | 不支持。 |
配置说明
- Redis Cluster集群实例 ,使用cluster nodes查询所有主备节点,客户端连接备节点,并在节点上做配置,开启备节点只读访问,从而实现读写分离。
查询集群节点命令如下:
redis-cli -h {redis_address} -p {redis_port} -a {redis_password} cluster nodes
从节点配置只读模式,请参考READONLY命令。
- Redis 4.0/5.0/6.0主备实例 ,在控制台的实例详情信息页面,域名区分可读写域名和只读域名,分别对应主节点和备节点,在客户端增加用户读写请求判断,如果是写请求,则将请求发送给读写域名,如果是读请求,则将请求发送给只读域名。
- 读写分离实例 ,默认为从服务端侧实现的读写分离,通过Proxy节点识别用户读写请求,如果是写请求,则转发给主节点,如果是读请求,则转发给备节点,不需要用户在客户端做任何配置。
Redis实例是否支持多DB方式?
Redis实例支持多DB方式的情况如下:
- Redis单机、读写分离和主备缓存实例支持多数据库(多DB),默认256个,DB编号为0-255。默认使用的是DB0。多数据库主要用于数据隔离,每个数据库的大小不是平均分配,可能会出现一个数据库将实例的内存完全占用的情况。
- Redis Proxy集群默认只有一个DB。
- 如需购买多DB的Proxy集群实例请参考如何购买多DB的Proxy集群实例?。
- 购买单DB的Proxy集群实例后,如需开启多DB的操作请参考Proxy集群使用多DB限制。
说明Redis 3.0 proxy不支持开启多DB。
- Redis Cluster集群实例不支持多DB,只有一个DB,即DB0。
DB的个数不支持修改,每个DB的大小也不支持自定义。
如何确认实例是单DB还是多DB
单机、主备、读写分离实例类型都为多DB(256个,DB编号为0-255)。
Proxy集群实例默认只有一个DB,支持手动开启多DB,如需开启多DB的操作请参考Proxy集群使用多DB限制。
Redis Cluster集群实例不支持多DB,只有一个DB。
Redis 4.0及以上版本的实例,通过控制台连接redis实例后,即可以查看是否为多DB,如下图所示。
连接Redis
查看Database
Redis集群实例是否支持原生集群?
当前DCS Redis3.0版本支持Proxy集群,Redis4.0和5.0版本支持原生集群和Proxy集群。
什么是哨兵?
Sentinel概览
Redis Sentinel为Redis实现高可用。实际使用中,您可以使用Sentinel帮助Redis在无需人工干预的情况下抵御某些类型的故障,Redis Sentinel还能够完成其他辅助任务,如监控、通知和客户端配置。详细介绍可参考Redis官网。
Sentinel原理
Redis Sentinel是一个分布式系统,Sentinel的设计基础在于多个Sentinel进程协同工作,这样做的好处有:
- 只有当多个哨兵一致同意某主节点不可用,才执行故障检测,这能够降低误报的可能性。
- 即使有些Sentinel进程故障,Sentinel系统也能正常工作,从而抵御故障。
从更大范围来看,Sentinel加上Redis主从节点以及连接到Sentinel和Redis的客户端,整体也构成一个更大的分布式系统。
Sentinel功能
- 监控:Sentinel不间断地检查主从节点是否都在正常工作。
- 通知:如果Redis中某节点故障,Sentinel可以通过API通知系统管理员或其他计算机程序。
- 自动故障切换:如果主节点异常,Sentinel启动故障切换,将一个从节点升主,其他从节点从新的主节点进行复制,并通知使用该Redis的应用程序使用新地址进行连接。
- 客户端配置来源:Sentinel充当客户端服务发现的权威来源。客户端连接到Sentinel,请求当前负责特定业务的Redis主节点地址。如果发生故障切换,Sentinels将下发新地址。
Redis实例是否支持配置哨兵模式?
Redis 4.0/5.0/6.0主备实例,读写分离实例,以及集群实例的每个分片(每个分片也是一个主备实例),都使用哨兵模式(Sentinel)进行管理,Sentinel会一直监控主备节点是否正常运行,当主节点出现故障时,进行主备倒换。
Redis3.0不支持哨兵模式,使用的是keeplived进行监控,当主节点故障时进行主备切换,备节点自动接管服务。
Redis默认的数据逐出策略是什么?
逐出指将数据从缓存中删除,以腾出更多的存储空间容纳新的缓存数据,详情请参见官网逐出策略。Redis实例支持在配置运行参数中查看或修改Redis实例使用的逐出策略。
Redis实例支持的逐出策略
在达到内存上限(maxmemory)时Redis支持选择以下8种数据逐出策略:
- noeviction:在这种策略下,如果缓存达到了配置的上限,实例将不再处理客户端任何增加缓存数据的请求,比如写命令,实例直接返回错误给客户端。缓存达到上限后,实例只处理删除和少数几个例外请求。
- allkeys-lru:根据LRU(Least recently used,最近最少使用)算法尝试回收最少使用的键,使得新添加的数据有空间存放。
- volatile-lru:根据LRU(Least recently used,最近最少使用)算法尝试回收最少使用的键,但仅限于在过期集合的键,使得新添加的数据有空间存放。
- allkeys-random:回收随机的键使得新添加的数据有空间存放。
- volatile-random:回收随机的键使得新添加的数据有空间存放,但仅限于在过期集合的键。
- volatile-ttl:回收在过期集合的键,并且优先回收存活时间(TTL)较短的键,使得新添加的数据有空间存放。
- allkeys-lfu:从所有键中驱逐最不常用的键。
- volatile-lfu:从具有“expire”字段集的所有键中驱逐最不常用的键。
说明当没有键满足回收前提条件时,数据逐出策略volatile-lru、volatile-random、volatile-ttl与noeviction策略相同,具体见上文noeviction介绍。
查看或修改Redis实例使用的逐出策略
Redis实例支持通过修改maxmemory-policy参数配置,查看及修改实例的数据逐出的策略。
使用redis-exporter出错怎么办?
通过在命令行启动redis-exporter,根据界面输出,查看是否存在错误,根据错误描述,进行问题排查。
[root@ecs-swk /]./redis_exporter -redis.addr 192.168.0.23:6379
INFO[0000] Redis Metrics Exporter V0.15.0 build date:2018-01-19-04:08:01 sha1: a0d9ec4704b4d35cd08544d395038f417716a03a
Go:go1.9.2
INFO[0000] Providing metrics at :9121/metrics
INFO[0000] Connecting to redis hosts: []string{192.168.0.23:6379}
INFO[0000] Using alias:[]string{""}
Redis的安全加固方面有哪些建议?
在众多开源缓存技术中,Redis无疑是目前功能最为强大,应用最多的缓存技术之一,但是原生Redis版本在安全方面非常薄弱,很多地方不满足安全要求,如果暴露在公网上,极易受到恶意攻击,导致数据泄露和丢失。
针对DCS的Redis实例,您在使用过程中,可参考如下建议:
- 网络连接配置
a. 敏感数据加密后存储在Redis实例。
对于敏感数据,尽量加密后存储。
b. 对安全组设置有限的、必须的允许访问规则。
安全组与VPC均是用于网络安全访问控制的配置,以端口最少放开原则配置安全组规则,降低网络入侵风险。
c. 客户端应用所在ECS设置防火墙。
客户端应用所在的服务器建议配置防火墙过滤规则。
d. 设置实例访问密码。
e. 配置实例白名单。
- Redis-cli使用
f. 隐藏密码
安全问题:通过在redis-cli指定-a参数,密码会被ps出来,属于敏感信息。
解决方案:修改Redis源码,在main方法进入后,立即隐藏掉密码,避免被ps出来。
g. 禁用脚本通过sudo方式执行
安全问题:redis-cli访问参数带密码敏感信息,会被ps出来,也容易被系统记录操作日志。
解决方案:改为通过API方式(Python可以使用redis-py)来安全访问,禁止通过sudo方式切换到dbuser帐号使用redis-cli。
Redis3.0 Proxy集群不支持redisson分布式锁的原因
redisson分布式锁的加锁和解锁流程如下:
- redisson分布式锁的加锁和解锁都是执行一段lua脚本功能实现的。
- 在加锁阶段,需要在lua脚本中执行exists、hset、pexpire、hexists、hincrby、pexpire、pttl命令。
- 在解锁阶段,需要在lua脚本中执行exists、publish、hexists、pexpire、del命令。
由于Proxy集群支持publish/subscribe(redis的发布订阅)时,是需要在Proxy节点上识别publish/subscribe命令,做一些特殊处理(转发给所有redis-server的节点),因此不支持直接在lua脚本中执行publish命令。
因此,Redis3.0 Proxy集群无法支持redisson的分布式锁机制,如果需要使用redisson分布式锁功能,建议使用Redis4.0或Redis5.0集群。
实例是否支持自定义或修改端口?
- Redis3.0
VPC内使用实例6379端口。
如果实例与客户端的安全组不同,还需要修改安全组配置,放开端口访问。具体修改方法,请参考:安全组配置与选择。
自定义端口
创建Redis 4.0/5.0/6.0实例时,可在"IP地址"配置项后输入指定的端口号,如不指定,则为默认的端口号6379。
修改端口
Redis 4.0/5.0/6.0实例创建后,如需修改端口号,可按如下步骤操作:
- 单击DCS控制台左侧菜单栏的“缓存管理”,进入缓存实例管理页面。
- 单击需要修改端口的实例名称,进入实例基本信息页。
- 在“连接信息”区域,单击“连接地址”后的,可修改端口。
注意Redis实例的访问端口修改后,Redis实例的所有连接将会中断,业务需要重新连接Redis的新端口。
实例是否支持修改访问地址?
DCS实例创建后,实例连接地址不支持修改。
如果需要更换实例IP地址,需要重新创建实例,在创建实例时,选择“手动分配IP地址”,指定实例的IP地址,然后使用在线迁移方式,将旧的实例数据迁移到新的实例。
有关DCS实例的客户端访问,请参考连接缓存实例。
实例无法删除是什么原因?
可能原因如下:
- 实例资源为包周期实例。
包周期的实例不支持删除操作,界面没有“删除”按钮,用户需要执行“退订”操作,退订实例资源。
- 实例资源不是“运行中”。
只有当实例处于“运行中”状态,才能执行删除操作。
- 确认实例是否为创建失败的实例。
如果是创建失败的实例,必须单击“创建失败任务”后的图标或者数量,进入“创建失败任务”界面,进行实例删除。
DCS实例是否支持跨可用区部署?
Redis主备、读写分离和集群实例支持跨可用区(AZ)部署。
- 当主备、读写分离实例进行跨可用区部署时,如果其中一个可用区故障,另一个可用区的节点不受影响。备节点会自动升级为主节点,对外提供服务,从而提供更高的容灾能力。
- 实例跨可用区部署时,主备节点之间同步效率与同AZ部署相比基本无差异。
集群实例启动时间过长是什么原因?
可能原因:在集群实例启动过程中,实例节点内部会进行状态、数据的同步。如果在完成同步之前就持续写入较多的数据,会导致实例内部同步耗费较长时间,实例状态一直处于“启动中”。直到同步完成,集群实例状态才会切换到“运行中”。
解决方案:建议等集群实例启动完成后,再恢复业务数据写入。
DCS Redis有没有后台管理软件?
没有。Redis的配置信息与使用信息可通过Redis-cli查询;对Redis实例的监控数据可通过云监控服务查看,监控数据的设置与查看方法,请参考监控章节。
DCS缓存实例的数据被删除之后,能否找回?
DCS缓存实例自行删除或者通过Redis客户端发送命令手动删除的数据,不能找回。如果实例执行了备份操作,则通过备份文件可以对数据进行恢复,但是恢复会覆盖备份时间到恢复这段时间的写入数据。
主备、集群和读写分离实例通过控制台的“备份与恢复”功能将已备份的数据恢复到DCS缓存实例中,参考实例恢复。
另外,如果DCS缓存实例被删除,实例中原有的数据将被删除,实例的备份数据也会删除,请谨慎操作。在删除实例之前,您可以将实例的备份文件下载,本地永久保存,如需恢复数据,可将本地备份文件迁移到新的实例中。下载备份数据的方式,请参考下载实例备份文件。
如何估算Redis内存占用量
Redis内存占用量,可参考Redis中文网站进行估算:http://www.redis.cn/redis_memory/。
估算和实际占用会存在差异,当前DCS Redis提供了以下与内存相关的指标。
Redis3.0实例支持的监控指标
指标ID | 指标名称 | 含义 | 取值范围 | 测量对象&维度 | 监控周期(原始指标) |
---|---|---|---|---|---|
memory_usage | 内存利用率 | 该指标用于统计测量对象的内存利用率。单位:%。 | 0-100% | 测量对象:Redis实例(单机/主备/集群)测量维度:dcs_instance_id | 1分钟 |
used_memory | 已用内存 | 该指标用于统计Redis已使用的内存字节数。单位:byte。 | >=0byte | 测量对象:Redis实例(单机/主备/集群)测量维度:dcs_instance_id | 1分钟 |
used_memory_dataset | 数据集使用内存 | 该指标用于统计Redis中数据集使用的内存单位:byte。 | >= 0byte | 测量对象:Redis实例(单机/主备/集群)Redis4.0以后的版本才支持测量维度:dcs_instance_id | 1分钟 |
used_memory_dataset_perc | 数据集使用内存百分比 | 该指标用于统计Redis中数据内存所占当前已用总内存的百分比单位:%。 | 0-100% | 测量对象:Redis实例(单机/主备/集群)Redis4.0以后的版本才支持测量维度:dcs_instance_id | 1分钟 |
used_memory_rss | 已用内存RSS | 该指标用于统计Redis已使用的RSS内存。即实际驻留“在内存中”的内存数。包含堆内存,但不包括换出的内存。单位:byte。 | >=0byte | 测量对象:Redis实例(单机/主备/集群)测量维度:dcs_instance_id | 1分钟 |
memory_frag_ratio | 内存碎片率 | 该指标用于统计当前的内存碎片率。其数值上等于used_memory_rss / used_memory。 | >=0 | 测量对象:Redis实例(单机/主备/集群)测量维度:dcs_instance_id | 1分钟 |
used_memory_peak | 已用内存峰值 | 该指标用于统计Redis服务器启动以来使用内存的峰值。单位:byte。 | >=0byte | 测量对象:Redis实例(单机/主备/集群)测量维度:dcs_instance_id | 1分钟 |
used_memory_lua | Lua已用内存 | 该指标用于统计Lua引擎已使用的内存字节。单位:byte。 | >=0byte | 测量对象:Redis实例(单机/主备/集群)测量维度:dcs_instance_id | 1分钟 |
Redis4.0和Redis5.0实例支持的监控指标
指标ID | 指标名称 | 含义 | 取值范围 | 测量对象&维度 | 监控周期(原始指标) |
---|---|---|---|---|---|
memory_usage | 内存利用率 | 该指标用于统计测量对象的内存利用率。单位:%。 | 0-100% | 测量对象:Redis实例(单机/主备/集群)测量维度:dcs_instance_id | 1分钟 |
used_memory | 已用内存 | 该指标用于统计Redis已使用的内存字节数。单位:byte。 | >= 0byte | 测量对象:Redis实例(单机/主备/集群)测量维度:dcs_instance_id | 1分钟 |
used_memory_dataset | 数据集使用内存 | 该指标用于统计Redis中数据集使用的内存单位:byte。 | >= 0byte | 测量对象:Redis实例(单机/主备/集群)测量维度:dcs_instance_id | 1分钟 |
memory_frag_ratio | 内存碎片率 | 该指标用于统计当前的内存碎片率 | >= 0 | 测量对象:Redis实例(单机/主备/集群)测量维度:dcs_instance_id | 1分钟 |
used_memory_lua | Lua已用内存 | 该指标用于统计Lua引擎已使用的内存字节单位:byte | >= 0byte | 测量对象:Redis实例(单机/主备/集群)测量维度:dcs_instance_id | 1分钟 |
used_memory_peak | 已用内存峰值 | 该指标用于统计Redis服务器启动以来使用内存的峰值单位:byte | >= 0byte | 测量对象:Redis实例(单机/主备/集群)测量维度:dcs_instance_id | 1分钟 |
Cluster集群实例容量和性能未达到瓶颈,但某个分片容量或性能已过载是什么原因?
这是由于Cluster集群采用的是分片设计理念,每个 具体的Key只能分布到某一个具体的分片节点上 ,计算Key的分布过程有以下两个步骤:
- 针对Key值进行CRC16算法计算后对16384取模,得到对应的槽位(Slot)值。
- 根据S槽位(Slot)和分片的映射关系,找到Key具体应该属于的分片,并且进行存取。
所以,Key并没有均匀分布在实例的各个分片上,是根据计算结果进行存取的。在大Key和热Key存在时,就会出现某个分片容量或性能已过载,但其他分片内存负载还是很低,并没有达到容量和性能的瓶颈。
DCS是否支持外部扩展模块、插件或者Module?
云上Redis不支持加载外部扩展模块、插件和Module。DCS后续也没有module的规划。
访问Redis返回“Error in execution”
访问Redis返回Error in execution; nested exception is io.lettuce.core.RedisCommandExecutionException: OOM command not allowed when used memory > 'maxmemory'。
OOM代表的就是超过了最大内存,报错中OOM command not allowed when used memory > 'maxmemory'的‘maxmemory’这个参数是Redis服务端对最大内存的配置,可以看到这个是内存使用满了。
若Redis实例内存使用率并未达到100%,有可能当前写入数据的那个节点的mem达到最大值。通过redis-cli -h <redis_ip> -p 6379 -a <redis_password> -c --bigkeys 连接到集群的各个节点进行分析。如果连接的从节点,需要在执行bigkeys命令之前,先发送READONLY命令。
Redis key丢失是什么原因
redis实例是不会主动丢失数据的,key丢失一般有这几种情况:1、key过期;2、key被逐出;3、key被删除。
按照顺序进行排查:
- 查看key是否过期。
- 查看监控,分析是否会触发键逐出机制。
- 去服务端分析info查看是否有删除key的操作。
访问Redis报OOM错误提示
问题描述
访问Redis返回Error in execution; nested exception is io.lettuce.core.RedisCommandExecutionException: OOM command not allowed when used memory > 'maxmemory'。
问题排查
OOM代表的就是超过了最大内存,报错中OOM command not allowed when used memory > 'maxmemory'的‘maxmemory’这个参数是Redis服务端对最大内存的配置,可以看到这是内存使用满了。
若Redis实例内存使用率并未达到100%,有可能当前写入数据的那个节点的mem达到最大值。通过redis-cli -h <redis_ip> -p 6379 -a <redis_password> -c --bigkeys连接到集群的各个节点进行分析。如果连接的从节点,需要在执行bigkeys命令之前,先发送READONLY命令。
不同编程语言如何使用Cluster集群客户端
当前DCS Cluster集群对比Proxy集群的优势和特性:
Cluster集群与Proxy集群差异
对比项 | Cluster集群 | Proxy集群 |
---|---|---|
原生兼容性 | 高 | 中 |
客户端兼容性 | 中(需要客户端开启集群模式) | 高 |
性价比 | 高 | 中 |
时延 | 低时延 | 中等时延 |
读写分离 | 原生支持(客户端SDK配置) | Proxy实现 |
性能 | 高 | 中 |
Cluster集群由于没有代理层,在时延和性能方面具备一定的优势;但是对于客户端使用方面,由于Cluster集群使用开源的Redis Cluster协议,在客户端的兼容性方面略差与Proxy集群。
推荐的Cluster集群客户端:
Cluster集群客户端
客户端语言 | 客户端类型 | Cluster集群参考文档 |
---|---|---|
Java | Jedis | https://github.com/xetorthio/jedis#jedis-cluster |
Java | Lettuce | https://github.com/lettuce-io/lettuce-core/wiki/Redis-Cluster |
PHP | php redis | https://github.com/phpredis/phpredis#readme |
Go | Go Redis | Cluster集群:https://pkg.go.dev/github.com/go-redis/redis/v8#NewClusterClientProxy集群或单机主备:https://pkg.go.dev/github.com/go-redis/redis/v8#NewClient |
Python | redis-py-cluster | https://github.com/Grokzen/redis-py-cluster#usage-example |
C | hiredis-vip | https://github.com/vipshop/hiredis-vip?_ga=2.64990636.268662337.1603553558-977760105.1588733325 |
C++ | redis-plus-plus | https://github.com/sewenew/redis-plus-plus?_ga=2.64990636.268662337.1603553558-977760105.1588733325#redis-cluster |
Node.js | node-redisio-redis | https://github.com/NodeRedis/node-redis https://github.com/luin/ioredis |
官方推荐的开源客户端列表:https://redis.io/clients。
使用Cluster的Redis集群时建议配置合理的超时时间
客户端配置问题导致无法连接。
当集群实例备节点故障情况下,客户端使用SpringBoot + Lettuce的方式连接Redis,使用的Lettuce客户端在连接集群时,需要与所有节点先建立连接(包括故障节点)。
- 在未配置timeout超时的情况下,模拟备节点故障时,可能出现分钟级的超时阻塞(Lettuce客户端的老版本默认超时为120s,新版本默认为60s),配置如下图:
可能会导致端到端业务访问时间过长(最长达到默认超时时间),如下图所示:
在客户端侧添加timeout参数后,备节点超时时间大幅度缩短,并且可以根据客户自己的业务诉求进行调整,配置如下:
配置后查看端到端业务访问时间如下图所示:
因此在未配置timeout参数情况下,客户端在建立连接时,故障节点由于未配置timeout超时,在建立连接时会出现连接阻塞的情况。
建议:用户需根据业务能容忍的超时时间进行设置,例如在一次HTTP端到端请求中,需要请求两次Redis,而HTTP请求的最大超时时间为10s,则建议将超时时间配置为5s,防止由于超时时间过长或者未配置超时时间造成故障场景下的业务受损。
Proxy集群使用多DB限制
DCS对于实现多DB存在一定的约束,建议针对客户业务进行评估:
- 使用约束:
a. swapdb不支持多DB。
b. info keyspace不支持多DB展示。
c. 需要查询每个DB的key总数,可以使用自定义dbstats命令。命令执行数据节点上会有CPU冲高。
d. LUA脚本中不支持多DB。
e. RANDOMKEY命令不支持。
f. 事务命令中不支持嵌入select命令。
g. 不支持在lua脚本中使用publish。
h. DB数支持范围为0 ~ 255。
i. Redis 3.0 proxy不支持开启多DB。
- 性能约束:
a. flushdb命令采用逐个key删除的方式执行,耗时久,慢于开源原生实现,速度与SCAN命令相同(需要客户实际测试)。
j. dbsize命令耗时长,禁止在代码中使用。
k. 多DB场景下keys命令和scan命令性能会有损失(最多50%)。
- 其他约束:
后端存储会按照一定规则对key进行改写,导出RDB数据中的key不是原始的key,但通过Redis协议访问无影响。
单DB实例开启多DB操作步骤
实例默认不开启多DB,在开启和关闭多DB特性之前需要先清空数据,按照以下操作进行多DB开启。
步骤 1 登录分布式缓存服务控制台。
步骤 2 连接实例,执行flushall命令清空原有数据。
步骤 3 在缓存管理页面,单击缓存实例进入实例详情页面。
步骤 4 单击“实例配置 > 参数配置”进入参数配置页面。
步骤 5 单击multi-db参数后的“修改”,将参数运行值修改为“yes”。
步骤 6 单击“保存”,在修改参数配置弹框中单击“是”开启多DB完成,无需重启实例。
实例是否支持变更可用区
不支持直接变更可用区。
如需改变可用区,可通过“数据迁移+交换IP”方式的方式,在新的可用区创建实例后,进行数据迁移,实现可用区的变更。具体操作如下:
说明
Redis 4.0及以上版本的实例支持实例交换IP。
只有源实例和目标实例都为云服务Redis实例才支持实例交换IP。
前提条件
说明
Redis 4.0及以上版本的实例支持实例交换IP。
只有源实例和目标实例都为云服务Redis实例才支持实例交换IP。
- 准备目标实例,如果已有目标Redis,不需要重复创建,但在迁移之前,您需要清空实例数据,清空操作请参考清空实例数据。
如果没有清空,如果存在与源Redis实例相同的key,迁移后,会覆盖目标Redis实例原来的数据。
- 创建的目标Redis与源Redis和迁移任务资源所在VPC需在同一个VPC内。
- 创建的目标实例端口需要与源实例保持一致。
- 进行实例交换IP满足的条件为:
− 进行实例IP交换依赖的是数据迁移功能,所以,源实例及目标实例必须支持数据迁移功能,详见DCS支持的迁移能力。
− 交换IP支持的能力如下表。
交换ip能力
源端 | 目标端 |
---|---|
单机/主备/读写分离 | 单机/主备/读写分离/proxy集群 |
Proxy集群 | 单机/主备/读写分离/proxy集群 |
交换IP须知
- 交换IP过程中,会自动停止在线迁移任务。
- 交换实例IP地址时,会有一分钟内只读和秒级的闪断。
- 请确保您的客户端应用具备重连机制和处理异常的能力,否则在交换IP后有可能需要重启客户端应用。
- 源实例和目标实例不在同一子网时,交换IP地址后,会更新实例的子网信息。
- 如果源端是主备实例,交换IP时不会交换备节点IP,请确保应用中没有直接引用备节点IP。
- 如果应用中有直接引用域名,请选择交换域名,否则域名会挂在源实例中。
- 请确保目标Redis和源Redis密码一致,否则交换IP后,客户端会出现密码验证错误。
- 当源实例配置了白名单时,则在进行IP交换前,保证目标实例也配置同样的白名单。
交换IP操作步骤
步骤 1 登录分布式缓存服务管理控制台。
步骤 2 在管理控制台左上角单击,选择实例所在的区域。
步骤 3 单击左侧菜单栏的“数据迁移”,页面显示迁移任务列表页面。
步骤 4 单击右上角的“创建在线迁移任务”。
步骤 5 设置迁移任务名称和描述。
步骤 6 配置在线迁移任务虚拟机资源的VPC、子网和安全组。
创建在线迁移任务时,需要选择迁移虚拟机资源的VPC和安全组,并确保迁移资源能访问源Redis和目标Redis实例。
步骤 7 配置迁移任务,此处迁移方式只能选择“全量迁移+增量迁移”。
步骤 8 在“在线迁移”页面,当迁移任务状态显示为“增量迁移中”时,单击操作列的“更多 > 交换IP”打开交换IP弹框。
步骤 9 在交换IP弹框中,在交换域名区域,选择是否交换域名。
说明
如果使用域名,则必须要选择交换域名,否则客户端应用需要修改使用的域名。
如果没有使用域名,则直接更新两个实例的DNS。
步骤 10 单击“确定”,交换IP任务提交成功,当迁移任务的状态显示为“IP交换成功”,表示交换IP任务完成。
回滚IP操作步骤
若您想将实例IP切换成原始的IP,请执行以下操作。
步骤 1 登录分布式缓存服务管理控制台。
步骤 2 在管理控制台左上角单击,选择实例所在的区域。
步骤 3 单击左侧菜单栏的“数据迁移”。
步骤 4 在“在线迁移”页面,迁移任务状态为“IP交换成功”,单击操作列的“更多 > 回滚IP”。
步骤 5 在确认框中,单击“确定”,IP回滚任务提交成功。但任务状态显示为“IP回滚成功”表示回滚任务完成。
hashtag的原理、规则及用法示例
hashtag原理
单实例上的mset、lua脚本等处理多key时,是一个原子性(atomic)操作,所有给定key都会在同一时间内被执行。集群每次通过对key进行hash计算到不同的分片,所以集群上同时执行多个key,不再是原子性操作,会存在某些给定 key 被更新而另外一些给定key没有改变的情况,其原因是需要设置的多个key可能分配到不同的机器上。因此集群引入了hashtag来对多key同时操作,在设置了hashtag的情况下,集群会根据hashtag决定key分配到的slot, 当两个key拥有相同的hashtag时, 它们会被分配到同一个slot。
hashtag使用规则
第一次出现“{”和接下来第一次出现的“}”之间有内容。
例如:
- 这两个键{user1000}.following和{user1000}.followers由于只有一对{},将user1000来计算hash。
- 对于键foo{}{bar},整个键foo{}{bar}将像往常一样计算hash,因为第一次出现的“{”后面跟“}”中间没有字符。
- 对于键foo{{bar}}zap,子字符串{bar将被计算hash,因为它是第一次出现“{”和第一次出现“}”之间的子字符串。
- 对于键foo{bar}{zap}的子字符串bar将被计算hash,因为只使用第一个“{”和“}”。
hashtag用法示例
当如下操作时:
EVAL "redis.call('set',KEYS[1],ARGV[1]) redis.call('set',KEYS[2],ARGV[2])" 2 key1 key2 value1 value2
出现以下报错:
ERR 'key1' and 'key2' not in the same slot
可通过hashtag进行解决:
EVAL "redis.call('set',KEYS[1],ARGV[1]) redis.call('set',KEYS[2],ARGV[2])" 2 {user}key1 {user}key2 value1 value2
重启实例后缓存数据会保留吗?
单机缓存实例重启后,原有的数据将被删除。
主备和集群实例(单副本集群除外)默认支持AOF持久化,实例重启后原有的数据会保留。
如主备和集群实例关闭了AOF持久化(appendonly参数修改为no即AOF持久化功能关闭),实例重启后原有的数据将被删除。
如何购买多DB的Proxy集群实例?
购买Proxy集群实例时,默认DB数为1,如需购买多DB的Proxy集群实例,请参考如下步骤:
说明购买多DB Proxy集群实例前,建议了解Proxy集群使用多DB限制。
步骤 1 登录分布式缓存服务管理控制台。
步骤 2 在管理控制台左上角单击,选择区域。
步骤 3 单击“参数模板”进入“系统默认模板”页面。
步骤 4 选择要创建的缓存版本和类型(Proxy集群),单击对应的“创建为自定义模板”。
步骤 5 将“参数配置”下的“multi-db”设置为yes。
步骤 6 输入新的模板名称后单击“确定”,创建自定义模板成功。
步骤 7 单击“缓存管理>购买缓存实例”,创建Proxy集群实例。
创建实例时,需将“参数配置”选择为“使用自定义模板”,并选择如上步骤中创建的自定义模板,即可创建多DB的Proxy集群实例。
创建成功后,可连接Redis查看是否为多DB实例。