redis集群redisKey分步不均匀问题

问题描述

项目中使用了redis集群,但是生产上发现redisKey 80%都被分配到了同一个节点,导致该节点磁盘容量报警,其余节点闲置的情况

问题定位

项目中为了保持数据的准确性,当系统发送异常时

  • 使用了LUA脚本对本次请求的redis操作进行了批量回滚(可实现redis批量操作的原子性)
  • LUA脚本仅支持对同一节点上的Key批量操作,所以redisKey使用了统一的前置{redisClusterPrefix:}

问题原理

  • 对于客户端请求的key,根据公式HASH_SLOT=CRC16(key) mod 16384,计算出映射到哪个分片上,然后Redis会去相应的节点进行操作
  • keySlot算法中,如果key包含{},就不对整个key做hash,而是使用第一个{}内部的字符串作为hash key,这样就可以保证拥有同样{}内部字符串的key就会拥有相同slot

单实例上的MSET是一个原子性(atomic)操作,所有给定 key 都会在同一时间内被设置,某些给定 key 被更新而另一些给定 key 没有改变的情况,不可能发生。

而集群上虽然也支持同时设置多个key,但不再是原子性操作。会存在某些给定 key 被更新而另外一些给定 key 没有改变的情况。其原因是需要设置的多个key可能分配到不同的机器上。

##SINTERSTORE,SUNIONSTORE,ZINTERSTORE,ZUNIONSTORE

这四个命令属于同一类型。它们的共同之处是都需要对一组key进行运算或操作,但要求这些key都被分配到相同机器上。

这就是分片技术的矛盾之处:

即要求key尽可能地分散到不同机器,又要求某些相关联的key分配到相同机器。

Hash Tags

HashTag机制可以影响key被分配到的slot,从而可以使用那些被限制在slot中操作。

HashTag即是用{}包裹key的一个子串,如{user:}1, {user:}2

在设置了HashTag的情况下,集群会根据HashTag决定key分配到的slot, 两个key拥有相同的HashTag:{user:}, 它们会被分配到同一个slot,允许我们使用MGET命令。

通常情况下,HashTag不支持嵌套,即将第一个{和第一个}中间的内容作为HashTag。若花括号中不包含任何内容则会对整个key进行散列,如{}user:

HashTag可能会使过多的key分配到同一个slot中,造成数据倾斜影响系统的吞吐量,务必谨慎使用

Redis集群介绍

Redis 集群是一个提供在多个Redis间节点间共享数据的程序集。

Redis集群并不支持处理多个keys的命令,因为这需要在不同的节点间移动数据,从而达不到像Redis那样的性能,在高负载的情况下可能会导致不可预料的错误.

Redis 集群通过分区来提供一定程度的可用性,在实际环境中当某个节点宕机或者不可达的情况下继续处理命令. Redis 集群的优势:

  • 自动分割数据到不同的节点上。
  • 整个集群的部分节点失败或者不可达的情况下能够继续处理命令

这种结构很容易添加或者删除节点. 比如如果我想新添加个节点D, 我需要从节点 A, B, C中得部分槽到D上. 如果我想移除节点A,需要将A中的槽移到B和C节点上,然后将没有任何槽的A节点从集群中移除即可. 由于从一个节点将哈希槽移动到另一个节点并不会停止服务,所以无论添加删除或者改变某个节点的哈希槽的数量都不会造成集群不可用的状态

  • 为了实现集群的高可用,即判断节点是否健康(能否正常使用),redis-cluster有这么一个投票容错机制:如果集群中超过半数的节点投票认为某个节点挂了,那么这个节点就挂了(fail)。这是判断节点是否挂了的方法;
  • 那么如何判断集群是否挂了呢? -> 如果集群中任意一个节点挂了,而且该节点没有从节点(备份节点),那么这个集群就挂了。这是判断集群是否挂了的方法;
  • 那么为什么任意一个节点挂了(没有从节点)这个集群就挂了呢? -> 因为集群内置了16384个slot(哈希槽),并且把所有的物理节点映射到了这16384[0-16383]个slot上,或者说把这些slot均等的分配给了各个节点。当需要在Redis集群存放一个数据(key-value)时,redis会先对这个key进行crc16算法,然后得到一个结果。再把这个结果对16384进行求余,这个余数会对应[0-16383]其中一个槽,进而决定key-value存储到哪个节点中。所以一旦某个节点挂了,该节点对应的slot就无法使用,那么就会导致集群无法正常工作

为什么集群是16384个槽

CRC16算法产生的hash值有16bit,该算法可以产生2^16-=65536个值。换句话说,值是分布在0~65535之间。那作者在做mod运算的时候,为什么不mod65536,而选择mod16384

两个节点之间会定期发送ping/pong消息,交换数据信息,因为每秒钟,redis节点需要发送一定数量的ping消息作为心跳包,如果槽位为65536,这个ping消息的消息头太大了,浪费带宽

集群节点越多,心跳包的消息体内携带的数据越多。如果节点过1000个,也会导致网络拥堵。因此redis作者,不建议redis cluster节点数量超过1000个。
那么,对于节点数在1000以内的redis cluster集群,16384个槽位够用了。没有必要拓展到65536个

https://www.cnblogs.com/youngdeng/p/12855424.html

为什么集群必须最少6个节点

Redis集群至少需要3个主节点,因为投票容错机制要求超过半数节点认为某个节点挂了该节点才是挂了,所以2个节点无法构成集群,另外在加3个从节点,即最少需要6个节点

<think>好的,我现在需要处理用户关于软件运维工程师常见面试题及其答案的查询。首先,我得回顾用户提供的引用内容,确保回答准确并符合引用来源。用户要求结构清晰,分步解释,并且生成相关问题。同时,必须遵循系统级指令,如正确使用LaTeX格式,生成相关问题,并在引用处添加标识。 首先,用户引用了四个来源,其中引用[1]提到了高级运维工程师面试题汇总,引用[2]讨论了安全措施和一致性哈希算法,引用[3]涉及DevOps工程师的知识,引用[4]比较了线程和进程的优缺。需要确保回答覆盖这些方面,同时结合常见的运维面试问题。 接下来,需要整理常见的面试问题。根据引用内容,可能的问题包括: 1. 解释一致性哈希算法及其应用(来自引用[2])。 2. 如何保障系统安全(引用[2]提到的措施)。 3. DevOps相关工具和知识(引用[3])。 4. 线程与进程的区别(引用[4])。 5. 其他常见问题如Linux命令、故障排查、监控工具等。 需要将这些内容结构化,分回答每个问题,并确保每个引用正确标注。例如,在解释一致性哈希时,必须引用[2],在讨论DevOps工具时引用[3],线程和进程部分引用[4]。 同时,注意使用LaTeX格式,例如在技术术语或数学表达时,如一致性哈希的分布可能涉及数学表达式,需要用$...$或$$...$$。例如,节分布可以用哈希环表示,可能需要使用数学符号。 另外,生成的相关问题需要基于已回答内容,确保用户有进一步探索的方向。例如,关于一致性哈希的优化,系统安全的具体配置步骤,或者CI/CD管道的搭建细节。 最后,检查是否符合中文回答,避免使用Markdown,保持段落清晰,代码块用三个反引号包裹,正确添加引用标识。确保每个引用只在末尾出现一次,避免重复。</think>### 软件运维工程师常见面试题及解答 #### 1. **如何解释一致性哈希算法及其应用?** 一致性哈希算法用于分布式系统中数据的均匀分布,通过环形哈希空间将节和数据映射到同一环上。数据存储时,顺时针找到最近的节,从而减少节增减时的数据迁移量。例如,在缓存系统(如Redis集群)中,新节加入仅影响相邻区间的数据,避免全局重新哈希[^2]。 数学表达:若哈希函数为$h(key)$,节位置为$N_i$,则数据$D$的归属节满足$h(D) \leq N_j$且$N_j$为最小节。 #### 2. **如何保障服务器系统安全?** 核心措施包括: - **更新系统与软件**:定期修补漏洞。 - **防火墙配置**:限制非必要端口访问(如仅开放SSH端口22)。 - **入侵检测系统(IDS)**:监控异常流量模式。 - **禁用非必要服务**:通过`systemctl disable <service>`关闭无用服务。 - **强密码策略**:结合双因素认证(如Google Authenticator)。 #### 3. **DevOps工程师需掌握哪些工具?** - **CI/CD工具**:如Jenkins流水线脚本编写、GitLab CI的`.gitlab-ci.yml`配置。 - **配置管理**:Ansible Playbook实现自动化部署(示例:`ansible-playbook deploy.yml`)。 - **容器化技术**:Dockerfile构建镜像,Kubernetes管理Pod和Service。 - **监控工具**:Prometheus查询语言PromQL、Grafana仪表盘配置[^3]。 #### 4. **进程与线程的区别及适用场景** - **进程**:独立内存空间,稳定性高但资源消耗大,适合CPU密集型任务(如数值计算)。 - **线程**:共享进程内存,创建开销小,适合IO密集型任务(如网络请求处理),但需注意线程锁避免资源竞争[^4]。 #### 5. **Linux系统故障排查命令示例** ```bash # 检查磁盘空间 df -h # 查看内存使用 free -m # 分析日志(如Nginx错误日志) tail -f /var/log/nginx/error.log # 追踪进程系统调用 strace -p <PID> ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值