火山引擎 Redis 云原生实践

redis 简介Redis 是大家日常工作中使用较多的典型 KV 存储,常年位居 DB-Engines Key-Value 存储第一 。Redis 是基于内存的存储,提供了丰富的数据结构,支持字符串类型、哈希/列表/集合类型以及 stream 结构 。Redis 内置了很多特性,其中比较重要的有:
 

  • 复制:Redis 支持异步的全量和增量同步,可以把数据从 Master 复制到 Slave, 实现 Redis 数据的高可用 。
  • 持久化:支持数据的持久化,可以通过 RDB 和 AOF 机制实现数据落盘 。
  • 支持哨兵工具:哨兵工具的主要工作模式是监控 Master 节点的健康状况 。当发现 Master 节点不可用时,会主动执行 Failover, 把 Slave 节点提升成 Master,保证 Redis 服务的高可用 。
  • 提供集群模式:单体 Redis 实例受限于物理机内存,当需要很大的 Redis 集群容量时,可以使用 Redis 集群模式 。Redis 集群模式的原理是把保存在其中的数据做了分片,每一部分数据由不同的 Redis 实例承担 。
 
Redis 的典型应用场景有以下 3 种:
  • 缓存:因为 Redis 是基于内存的存储,它的读写请求会在内存执行,请求响应的延迟很低,所以很多场景下会把 Redis 当做缓存使用 。
  • 数据库:Redis 支持持久化,可以把它当做 KV 数据库使用 。
  • 消息队列:Redis 支持 stream 数据,在 stream 数据结构基础上封装了 pub-sub 命令,实现了数据的发布和订阅,即提供了消息队列的基本功能 。
 
Redis 协议是二进制安全的文本协议 。它很简单,可以通过 telnet 连接到一个 Redis server 实例上执行 get 和 set 操作 。
K8s 简介K8s 是一个容器编排系统,可以自动化容器应用的部署、扩展和管理 。K8s 提供了一些基础特性:
  • 自动装箱:可指定 K8s 里 Pod 所需资源的最小值和最大值,即 limit 和 request 的值 。K8s 可以根据 request 的值做 Pod 调度,在一个节点上拉起 Pod 。
  • 服务发现与负载均衡:K8s 提供基于 DNS 的服务发现机制,同时也提供基于 service 的负载均衡 。
  • 自动化上线和回滚:这里会涉及到 K8s 的工作负载资源 。K8s 提供几种不同的工作负载资源对应不同的业务场景 。这些不同的工作负载资源可以实现服务的配置变更,例如更新 image、升级 binary、进行副本的扩缩容等 。
  • 支持 Deployment/DaemonSet
  • 支持 StatefulSet
  • 支持 CronJob/Job
  • 水平扩缩容:K8s 天然支持水平扩缩容,可以基于 Pod 的 CPU 利用率、内存利用率以及第三方自定义 metrics 对 Pod 进行水平动态扩缩容 。
  • 存储编排:K8s 支持基于 PV 和 PVC 的存储供应模式,可以通过 PV 和 PVC 在 Pod 内部使用存储 。
  • 自我修复:举一个例子就是副本保持 。比如用 Deployment 来托管一个服务,如果 Deployment 下的一个 Pod 所在的宿主机出现了不可用的情况, K8s 会在可用的节点上重新拉起一个新的 Pod 来提供服务 。
 
现实工作中遇到的服务根据是否需要数据持久化可分为有状态服务和无状态服务 。不需要数据持久化的服务被认为是无状态的,包含以下几种类型:
  • API 类服务:可在任意节点上执行 。如果要在 K8s 上部署这类服务,可使用 K8s Deployment 。
  • Agent 或 Deamon 类服务:需要部署在每一台机器上,而且每台机器上最多部署一个进程 。在 K8s 上可选择 DaemonSet 来完成对应的部署 。
  • 还有一类无状态服务对固定的唯一标识有需求 。要满足这些需求,可使用 K8s 的 StatefulSet 来满足 。虽然 StatefulSet 是用来部署有状态服务的,但它可提供固定的唯一标识,也可用来托管无状态服务 。
 
有状态服务需要稳定的持久化存储 。除此之外,可能还会有一些其它的特性要求:
  • 稳定的唯一标识
  • 有序、优雅地部署和缩放
  • 有序的自动滚动更新
在 K8s 上,我们一般会用 StatefulSet resource 来托管有状态服务 。
Redis 云原生实践下面将介绍火山引擎 Redis 云原生实践 。首先我们会明确 Redis 云原生的目标,主要有以下几个: