千万流量秒杀系统-KV 存储:etcd 和 Redis 高可用原理和部署方法

秒杀场次信息是聚合根,它聚合了秒杀商品信息和秒杀专题信息。假如我们要从关系型数据库中提取场次详情,意味着需要访问三张表:活动专题表、活动场次表、活动商品表。

这会出现什么问题呢?一旦遇到高并发情况,数据库就会承受很高的访问压力甚至瘫痪。

那有没有办法解决这个问题,提高数据访问的高性能和高可用?有!那就是使用 KV 存储,这也是本讲的主题。

  • 什么是 KV 存储

KV 是 Key-Value 的缩写,KV 存储也叫键值对存储。简单来说,它是利用 Key 做索引来实现数据的存储、修改、查询和删除功能。

常用的高性能 KV 存储主要有 Redis、Memcached、etcd、Zookeeper 等,其中 Redis 和 Memcached 主要用来缓存业务数据, etcd 和 Zookeeper 主要用来存储元数据。

业务数据比较好理解,就是业务系统业务逻辑处理的数据。比如我们要在 API 服务中将活动信息快速读取出来,就需要用 Redis 做缓存,降低耗时,提升数据的吞吐能力。

那什么是元数据呢?在分布式系统中,元数据就是系统的基本信息,包括系统名称、服务名称、服务配置、节点 IP 等。比如秒杀系统中,秒杀服务调用商品中心和交易中心的时候,就需要从服务注册中心里获取这两个系统的元数据。

以上是对 KV 存储的基本介绍,一般在秒杀系统中,我们会利用 Redis 和 etcd 实现多级缓存和漏斗模型中的部分功能,比如缓存活动信息、存储秒杀 API 服务节点信息、利用分布式锁和消息队列将请求串行化等。

所以,接下来我就为你着重介绍下 KV 存储中 Redis 和 etcd 的高可用原理及其部署方法。

  • Redis 高可用原理及部署方法
  • Redis 的高可用原理
    你可能会问了,既然 Redis 和 Memcached 都可以缓存业务数据,那为什么会选择 Redis 而不是 Memcached 呢?

其实 Memcached 在性能上要稍微比 Redis 好,但在易用性和可用性上,Redis 要大大超过Memcached 。

先说易用性。Redis 有五种数据类型:list 、set 、string 、hash 、zset。这表示在使用 Redis 存储数据的时候将会更灵活,能节省很多开发成本。而 Memcached 支持的数据类型比较简单,只有 string,无法满足复杂业务场景的需求。

另外,Redis 还支持原子操作和事务,可以确保操作数据时的准确性,使用非常简单。比如在秒杀中扣减和归还库存,就可以用 Redis 的原子操作和事务来保障库存数据的准确性。

在可用性方面呢,Redis 支持 Master-Slave 模式的数据备份,而 Memcached 不支持; 在故障转移方面,Redis 的可用性也比 Memcached 高。

还有,Memcached 是纯内存的,崩溃后里面存储的信息就丢失了,而 Redis 则可以通过命令将内存中的数据保存到磁盘上,让数据持久化。

换句话说,即使 Redis 节点因为宕机导致内存中的数据丢失,它也可以从磁盘恢复数据到内存,这就大大降低了因宕机导致缓存穿透的风险。应用到秒杀系统里就是,假如秒杀活动进行中,缓存活动信息的 Redis 挂了,由于数据做了持久化,就避免了大量请求直接到 DB。

那 Redis 是如何做到高可用的呢?

它主要通过支持主从模式、哨兵模式、集群模式这三种模式,来满足不同业务特点和可用等级的需求。 其中,主从模式部署最简单,用得也最多,集群模式比较复杂,但可用性最高。具体怎么部署呢?

  • Redis 的部署方法

主从模式

主从模式比较简单,可部署多个节点,其中一个作为 Master 节点,剩下的作为 Slave 节点。它的示意图如下:

在这里插入图片描述

在主从模式里,客户端同时连接 Master 节点和 Slave 节点,写操作通过 Master 节点执行,并将结果同步给 Slave 节点,读操作通过 Slave 节点执行。假如 Master 节点挂了,不影响读操作,我们可以通过手动修改配置将某个 Slave 节点提升为 Master 节点,重新提供写能力。

主从模式最大的优点是部署简单,最少两个节点便可以构成主从模式,并且可以通过读写分离避免读和写同时不可用。不过,一旦 Master 节点出现故障,主从节点就无法自动切换,直接导致 SLA 下降。所以,主从模式一般适合业务发展初期,并发量低,运维成本低的情况。

后来,为了避免主从无法自动切换的问题,又出现了一种新模式——哨兵模式,它是主从模式的升级。

哨兵模式

哨兵模式是如何部署的呢?请看下图:

在这里插入图片描述

相比主从模式,哨兵模式新增了独立部署的节点——哨兵节点(Sentinel)。这些节点虽然不参与数据处理,但它们会像哨兵一样负责监控 Master 和 Slave 的状态及拓扑关系,并把主从关系信息提供给客户端。客户端在连接 Redis 的时候,会先连接哨兵节点,获取 Master 和 Slave 信息,然后再连接 Master 和 Slave。

在三种模式当中,哨兵模式是 Redis 官方推荐的高可用模式,那它是如何做到高可用的呢?

首先,哨兵集群会通过 Ping 和 Info 请求监控所有 Redis 节点的状态,并且哨兵集群内会选举出 Leader 节点。当 Master 节点挂了后,哨兵集群内部会进行投票,如果超过半数节点确认 Master 节点挂了,则会由哨兵集群的 Leader 节点选择一个 Slave 节点进行主从切换。最后,哨兵集群会将新的主从信息通知给客户端,让客户端连接到新的 Master 和 Slave 节点上。

哨兵模式适合读请求远多于写请求的业务场景,比如在秒杀系统中用来缓存活动信息。 如果写请求较多,当集群 Slave 节点数量多了后,Master 节点同步数据的压力会非常大。怎么办呢?为了解决写请求较多的业务场景, Redis 又提供了集群模式。

集群模式

集群模式具体是怎么部署的呢?请看下图:

在这里插入图片描述

为了避免单一节点负载过高导致不稳定,集群模式采用一致性哈希算法将 Key 分布到各个节点上。其中,每个 Master 节点后跟若干个 Slave 节点,用于出现故障时做主备切换。

在这种模式下,Master 节点可以同时处理读和写请求。具体来说,客户端可以连接任意 Master 节点,集群内部会按照不同 key 将请求转发到不同的 Master 节点。当然,为了减少 Master 内部转发请求的压力,也可以选择在客户端连接所有 Master 节点,直接在客户端将请求哈希到对应的 Master 节点。

集群模式是如何实现高可用的呢?集群内部节点之间会互相定时探测对方是否存活,如果多数节点判断某个节点挂了,则会将其踢出集群,然后从 Slave 节点中选举出一个节点替补挂掉的 Master 节点。

虽然集群模式避免了 Master 单节点的问题,但集群内同步数据时会占用一定的带宽。所以,只有在写操作比较多的情况下人们才使用集群模式,其他大多数情况,使用哨兵模式都能满足需求。

以上便是 Redis 常用的几种部署方法,不知道你是否掌握了呢?聊完 Redis,接下来我为你介绍下 etcd。
在这里插入图片描述

  • etcd 高可用原理及部署方法

etcd 和 Zookeeper 都可以存储集群元数据,以保障集群核心信息的高可用和高性能访问。其中**etcd 用的是 Raft 协议, Zookeeper 用的是 Paxos 协议,这两种分布式协议都满足 CAP 理论中的 CP。**也就是说,它们都满足一致性(Consistency)和分区容错(Partition tolerance)的要求。

但相比 Zookeeper ,这几年 etcd 在业界的认可度越来越高,多款重量级开源软件(如,Kubernetes、Traefik、Casbin)都使用了它。那么,人们为何会青睐 etcd 呢?

  • etcd 的高可用原理

和 Zookeeper 相比,etcd 有很大优势。

首先,etcd 支持 HTTPS 访问、划分命名空间、 RBAC 权限控制,可以有效保证数据安全。

特别是在易用性方面,etcd 是用 Golang 实现的,简单配置后就可以运行。同时,它还提供了 HTTP 接口和 gRPC 接口,非常方便客户端使用。另外,etcd 还支持订阅某个 Key 下的数据变更,假如这个数据被修改了,客户端能实时收到通知并获取最新的数据。

可用性方面,etcd 会将数据写入磁盘,不会因为节点宕机丢失数据。即便 etcd 集群当中有的节点宕机了,凭借 Raft 协议,也能保证集群稳定运行。

你可能会问了,什么是 Raft 协议,etcd 具体是如何用 Raft 协议做集群管理的呢?

简单来说,Raft 协议是 etcd 中保证分布式系统强一致性的算法。Raft 协议维护了集群节点的角色状态——Leader(领导者)、Follower(跟随者)、Candidate(候选者)。

其中,Leader 节点主要维护整个集群的运行状态,它负责通过 Raft 协议将写操作同步给所有节点,特别是通过心跳机制与 Follower 通信。而 Follower 节点主要负责把写请求和自身运行状态上报给 Leader,如果 Leader 任期结束或者心跳超时,Follower 会变成 Candidate 并发起选举。

这里的 Candidate 就是选举 Leader 过程中的候选者,当某个 Candidate 获得一半以上的票数, Candidate 就会成为 Leader,承担起维护集群运行的责任。其他 Candidate 自动转变成 Follower,继续发挥自己的作用。

除了选举出 Leader 维护集群信息外,etcd 对于每个 Key 的每次修改都会生成一个自增 ID 用于版本控制,并且会带上任期 ID, 确保集群各节点收到的数据版本一致并且是最新的。

以上便是 etcd 的高可用原理。可以说,正是因为 etcd 的这些优点,越来越多的系统开始用它保存关键数据。比如,秒杀系统经常用它保存各节点信息,以便控制消费 MQ 的服务数量。还有些业务系统的配置数据,也会通过 etcd 实时同步给业务系统的各节点,比如,秒杀管理后台会使用 etcd 将秒杀活动的配置数据实时同步给秒杀 API 服务各节点。

  • etcd 的部署方法

我们先看下它的架构图。
在这里插入图片描述

通常,etcd 会监听两个端口,默认是 2379 端口和 2380 端口。其中,2380 端口用于集群内部通信,主要涉及集群间数据同步、心跳、选举等。2379 端口用于与客户端通信,比如接收客户端发起的读/写数据请求。

etcd 节点在部署的时候有两种运行模式:集群模式和代理模式。

当 etcd 节点以集群模式运行时,它会加入已有集群中,作为集群的一部分。也就是说,后续的心跳、数据同步、选举等它都会参与。

集群模式中的节点数一般采用奇数个。为什么呢?因为假如同时有两个 Candidate 发起选举,如果是偶数节点的话,可能存在两个 Candidate 获得相同票数。

这会导致什么问题?如果两个 Candidate 票数一样,就需要再次发起选举,而再次发起选举还是有一定概率出现票数一样,这会导致选举耗时较多,影响稳定性。所以,采用奇数个节点,能有效降低票数一样的概率,提升选举的效率。另外,使用奇数节点来部署,也能让 etcd 很好地处理分区容错问题。

在这里插入图片描述

当某个 etcd 节点以代理模式运行时,该节点负责将接收到的请求转发给 etcd 集群节点。目前 etcd 接口有 v2 和 v3 两个版本,其中 v2 是 HTTP 接口,v3 是 gRPC 接口。需要注意的是,代理模式只支持转发 v2 版本的请求,也就是只支持转发 HTTP 请求。

在这里插入图片描述

不过,由于 etcd v3 接口在性能、安全、稳定性等方面要比 v2 接口优秀很多,新项目倾向于使用 v3 接口,老项目也逐渐从 v2 接口迁移到 v3 接口。也就是说,代理模式以后可能逐渐被淘汰掉。

关于 etcd 集群的具体搭建,etcd 官网有比较详细的教程和测试环境,感兴趣的话你可以上官网体验下。

小结
这一讲我们了解了常用 KV 存储中的 Redis 和 etcd 的高可用原理和部署方法,并且重点介绍了它们各种部署方式以及应用场景,不知道你是否掌握了吗?

前面我也提到了,在秒杀系统中,我们将利用 Redis 和 etcd 实现多级缓存和漏斗模型中的部分功能,具体的实现方法我会在模块七详细介绍。

请你思考下:假如秒杀系统有 5 个节点,只让其中一个节点能消费消息队列,如何使用 etcd 来实现这一功能呢?

可以把你的想法写在下面的留言区哦。

这一讲就介绍到这里,下一讲我将为你介绍如何防范重放攻击和 XSS 注入,到时见
在这里插入图片描述

本文章内容为转载,如有侵权请联系作者下架。

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值