一、背景

1.1、现状

Redis有数万个实例,每天百万亿次Redis访问,支撑了几乎所有的产品线和生态链。

1.2、问题

Redis部署在物理机上,不同业务间没有做资源隔离:
1、当 机器宕机 或 网络抖动,导致Redis节点下线,需要人工介入运维处理,运维成本高。
2、没有做CPU资源隔离,当slave节点打RDB或流量激增导致节点QPS高,会造成节点CPU使用率增加,导致无法预测的延迟增加,影响其他业务。
3、Redis分片采用Redis Cluster协议,集群自主分片。问题:应用开发人员需要一定程度了解Redis Cluster,同事需要使用智能客户端访问Redis Cluster。这些智能客户端配置参数繁多,应用开发人员不易掌握。

二、为什么要用K8S

2.1、为了资源隔离

为了提升资源利用率,多个业务混合部署,当使用物理机时,混步的不同业务间会互相影响。一旦出现问题,不同业务间会互相影响,定位及解决问题需要花费一定时间,代价较高。

用K8S后,可以做资源隔离,不同业务不会互相影响。

2.2、自动化部署

部署到物理机时,需要人工介入:查找空余资源的机器,再手动修改配置文件,部署节点,在使用工具创建集群,新集群初始化需要1~2小时。

K8S通过StatefulSet部署K8S集群,部署新集群只需要几分钟,大大提高运维效率,降低了运维成本。

三、怎样使用K8S

客户端通过LVS(LinuxVirtualServer,一个虚拟的服务器集群系统)的VIP统一接入,通过Redis Proxy转发服务请求到Redis Cluster集群。这里引入了Redis Proxy来转发请求:

3.1、Redis Cluster部署方式

Redis部署为StatefulSet, 作为有状态服务。
对于持久化存储部分,如RDB/AOF,可持久化到分布式存储中,重启后读取,性能会低于本地磁盘,但好在RDB/AOF是异步的,延迟一点可接受(延迟为100~200ms)

3.2、Proxy部署方式

Proxy作为无状态服务,通过LB对外提供服务,很容器做到动态扩缩容。同时,为Proxy开发了动态切换后端Redis Cluster的功能,用于实现在线添加和切换Redis Cluster。

可以利用K8S对Proxy自动扩缩容

四、为什么使用Proxy

4.1、用于解决Redis Pod重启后IP变化的问题

Redis Cluster的Redis客户端,需要配置集群部分节点的IP和Port, 用于客户端重启时查找Redis Cluster的入口。这对于物理机不是问题,物理机重启后IP和Port不会变化。

但在K8S上的Pod, 重启后IP会变化,这样客户端就可能找不到Redis Cluster的入口了。

解决方案:在客户端和Redis Cluster之间加上Proxy,可对客户端屏蔽调Redis Cluster的信息,由Proxy动态感知Redis CLuster上的节点变化,客户端只需要将LVS的IP:Port最欧文入口,请求转发到Proxy上即可,这样就可以像使用单机版Redis一样使用Redis Cluster集群了,也不需要Redis只能客户端。

4.2、Redis处理连接负载高

在Redis 6.0版本之前,Redis都是单线程处理大部分任务的。当Redis节点连接较高时,Redis需要消耗大量的CPU资源处理这些连接,导致时延较高。有了Proxy智慧,大量连接都在Proxy上,而Proxy跟Redis实例之间只保持很少的连接,这样降低了Redis的负担,避免了连接增加而导致Redis时延升高。

4.3、集群迁移切换需要应用重启

集群迁移时,当前物理机的方案为:

  • 按需创建新集群
  • 使用同步工具,将数据从老集群同步到新集群
  • 确认数据无误后,跟业务沟通,重启服务切换到新集群

但有了Proxy,可以将后端的创建、同步、切换集群 对客户端屏蔽掉。新老集群同步完成后,由Proxy切换地址,使客户端无感知。

4.4、数据安全风险

Redis通过AUTH来做鉴权,客户端直连Redis,密码在客户端保存,存在安全风险。如果使用proxy, 密码保存在proxy,且proxy可限制flushdb, config set等操作,避免了客户端误用的情况。

proxy上增加了高危操作的日志保存功能,可以在不影响性能前提下提供审计能力。

4.5、Proxy代来的问题

1、多一跳的时延

多一跳会增加0.2~0.3ms的时延,不过通常这对业务来说是可以接受的。

2、Pod漂移造成IP变化

proxy部署在k8s上,重启IP也会变化,通过LVS感知proxy IP变化,可动态把LVS的流量且到重启后的proxy上。

3、LVS带来的时延

LVS带来的时延,总体小于0.1ms

五、K8S带来的好处

5.1、部署方便

5.2、解决端口管理问题

目前小米部署Redis实例,是通过端口来区分的,并且下线的端口不能服用,也就是说每个Redis实例都要有唯一的端口号,最多能用65535各。
通过K8S,每个Redis实例都有独立的IP,不存在端口数的限制了。

5.3、提高客户端性能

用户不必使用智能客户端,可降低客户端的负载。因为智能客户端需要再客户端对key进行hash以确定发送到哪个redis节点,在qps比较高的情况下回消耗客户端机器的CPU资源。

5.4、动态升级和扩缩容

Proxy支持动态添加和切换Redis Cluster,这样Redis Cluster在集群升级和扩容切换时,业务端无感知。

举例说明:业务方使用了30个节点的Redis Cluster集群,当需要扩容2倍节点时,在原来的物理机上过程如下:

  • 协调资源,部署60个节点的新集群
  • 手动配置迁移工具,将当前集群的数据迁移到新集群
  • 验证数据无误后,通知业务方修改Redis Cluster的连接地址,重启服务。

虽然Redis Cluster支持在线扩容,但扩容过程中slots迁移会对线上服务造成影响,同时迁移时间不可控,所以不采用线上扩容。

新的k8s集群扩容过程如下:

  • 通过API接口,一键创建60个节点的新集群
  • 通用通过API接口,一键创建集群同步工具,将数据迁移到新集群
  • 验证数据无误后,向Proxy发送命令,添加新集群信息并完成切换。

整个过程,业务无感知。

集群升级也很方便:如果业务方能接受一定的延迟毛刺,可在低峰时段通过StatefulSet滚动升级方式来实现;如果业务对延迟有要求,可以通过创建新集群迁移数据的方式实现。

5.5、提高服务稳定性和资源利用率

通过k8s自带的资源隔离能力,实现和其他不同类型的应用混步,在提高资源利用率的同时,也能保证服务稳定性。

六、遇到的问题

6.1、Pod重启导致数据丢失

K8s的Pod遇到问题重启时,由于重启速度过快,会在Redis Cluster集群发现并切主前,将Pod重启。如果Pod上的Redis是slave,不会有任何影响。如果是master,并且没有AOF,重启后原来内存中的数据被清空,Redis会reload之前存储的RDB文件,但RDB文件并不是实时的数据。之后slave也会跟着把自己的数据同步成之前的RDB文件中的数据镜像,会造成部分数据丢失。

StatefulSet是有状态服务,部署的Pod名是固定格式(StatefulSet名+编号)。我们在初始化Redis Cluster时,将相邻编号的Pod设置为主从关系,在重启Pod时,通过Pod名确定他的slave,在重启Poad前向从节点发送cluster failover命令,强制将或者的从节点且住,这样在重启后,该节点会自动以从节点方式接入集群。

6.2、LVS映射时延

Proxy的Pod事通过LVS实现负载均衡的,LVS读以后端IP:Port的映射生效有一定时延,Proxy节点突然下线,会导致部分连接丢失。

对于正常的Proxy Pod下线,例如集群缩容、滚动更新proxy版本,及其他k8s可控的pod下线,在pod下线前,会发消息给LVS,并等待171秒,这段时间足够LVS将这个pod的流量逐渐切到其他pod上,对业务无感知。

6.3、K8s StatefulSet无法满足Redis Cluster部署要求

k8s原生的StatefulSet不能完全满足Redis Cluster部署的要求:
1、Redis Cluster不允许同为主备关系的节点部署在同一台机器上。
2、Redis Cluster不允许机器超过一半的主节点失效。因为超过一半主节点失效,就无法有足够的节点投票来满足gossip协议的要求。因为Redis Cluster的主备是可能随时切换的,我们无法避免同一个机器上的所有节点都是主节点,所以在部署时,不能允许集群中超过1/4的节点部署在一台机器上。

为了满足上面的要求,原生StatefuleSet可以通过anti-affinity功能来保证相同集群在同一机器上只部署一个节点,但这样集群利用率很低。

因此,我们开发了基于StatefuleSet的CRD:RedisStatefulSet, 会采用多种策略部署Redis节点。同时,还在RedisStatefuleSet中接入了一些Redis管理功能。

小米Redis容器化学习笔记相关推荐

  1. Docker最全教程——Redis容器化以及排行榜实战(十三)

    Docker最全教程--Redis容器化以及排行榜实战(十三) 原文:Docker最全教程--Redis容器化以及排行榜实战(十三) 前言 容器教程的路还很长,笔者尽量根据实践来不断地完善.由于在编写 ...

  2. Redis详细教程-学习笔记

    Redis 概述 Redis是什么? Redis(Remote Dictionary Server ),即远程字典服务,是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.K ...

  3. Redis狂神说学习笔记

    [狂神说Java]Redis视频 p1-3 企业架构演进 单机Mysql --> 多Mysql --> 主从复制,读写分离 --> 加入缓存 --> Mysql集群(数据分散在 ...

  4. Docker、Podman 容器“扫盲“ 学习笔记【与云原生的故事】

    [摘要] 笔记内容:由理论和具体docker常用操作构成.这篇博文笔记的定位是:温习,查阅,不适合新手学习.你拥有青春的时候,就要感受它,不要虚掷你的黄金时代,不要去倾听... 写在前面 笔记内容:由 ...

  5. Docker、Podman 容器“扫盲“ 学习笔记

    写在前面 之前只是做毕业设计时,接触一点,用DockFile在阿里云上部署了毕设.后来docker端口问题,机器被植入木马,拉去挖矿,cup天天爆满,百度半天删了好多文件不管用,后来恢复镜像了,之后在 ...

  6. redis源码学习笔记目录

    Redis源码分析(零)学习路径笔记 Redis源码分析(一)redis.c //redis-server.c Redis源码分析(二)redis-cli.c Redis源码剖析(三)--基础数据结构 ...

  7. Docker容器化技术笔记

    学习目标 掌握Docker基础知识,能够理解Docker镜像与容器概念 完成Docker安装与启动 掌握Docker镜像与容器相关命令 掌握Tomcat Nginx等软件的常用应用的安装 掌握dock ...

  8. 小米生态链战地学习笔记

    前言 本年度开始在微信读书上发现这些大企业实战的书,希望从中学习做产品,创业上的经验,将自己学习到的几点做成笔记. 背景 17年的时候,此时小米围绕着手机及电子消费市场,已经颇有成绩,此时对从12年左 ...

  9. Redis深度历险 学习笔记

    一.Redis基本数据结构类型 1.string 实现方式是数组,类似于java的ArrayList.单个字符串最大512M,字符串需要扩容时:小于1M扩容一倍:大于1M,最多只扩容1M. 使用场景: ...

最新文章

  1. oracle-01031+linux,Linux下,“ORA-01031: insufficient privileges”的处理
  2. nchoosek--二项式系数或所有的组合数
  3. BZOJ 3156: 防御准备( dp + 斜率优化 )
  4. 配置EIGRP默认路由
  5. [渝粤教育] 西南科技大学 工程建设监理 在线考试复习资料
  6. java解析xml串标签_Java反射解析XML字符串并封装到指定的JavaBean
  7. 论文笔记_S2D.10-2016-NIPS_室外单张图像的深度感知
  8. 炉石传说游戏系统拆解和部分系统分析
  9. 网卡驱动离线安装经验,避坑指南
  10. 超细节的QT设计完整界面布局的流程-新手向
  11. No virtual method
  12. 【黑马程序员】vue学习笔记(未完)
  13. 集线器、交换机、路由器、网桥、网关之间的区别
  14. 大数据面前,统计学的价值在哪里
  15. “夕阳无限好,只是近黄昏”改一个什么字让意境与原句截然不同?
  16. 关于linux下的嵌入式文件系统以及flash文件系统选择(转)
  17. 嘉立创电路板制作过程全流程详解(二):沉铜、线路
  18. 网站建设与管理的基本概念
  19. 在线制作流程图的实用工具网站
  20. 从《西游》《魔界》看东西方的团队与项目管理

热门文章

  1. 警察局计算机专业女生,毕业照令人羡慕,全系就一个女生,网友表示:后悔曾报考的专业了...
  2. 《图解HTTP精华解读》笔记
  3. pdf怎么转化成cad文件?转换软件分享
  4. php判断新数据类型,ThinkPHP发布5.2RC1版本
  5. 2023年上半年PETS5报名及考试时间正式公布
  6. 深度学习--自编码器(AutoEncoder)
  7. DB2 SQL语句的优化
  8. 2021年哔哩哔哩Java高级面试题及答案,面试必问!
  9. 《程序员羊皮卷》中的职场江湖
  10. vscode设置pythonPath