路由条目包含什么中“S 30.0.0.0【1/0】 vir 20.0.0.1”的含义?

本文档所含信息适用于所有平台

夲文旨在提供关于 RAC 环境中最常见的数据库和/或实例性能问题的摘要以及可能的解决方案

请注意问题 3(Mutexes 上的大量等待)和问题 5(高 CPU 和内存開销)是一般性数据库问题,并非特定于 RAC 的问题不过,本文中讨论这些问题是因为这些是最常见的问题之一会在 RAC 环境中的某一个实例發生。

//viewspace-2130835/如需转载,请注明出处否则将追究法律责任。

etcd 是 Kubernetes 集群中存储元数据保证分布式一致性的组件,它的性能往往影响着整个集群的响应时间而在 K8s 的使用中,我们发现除了日常的读写压力外还存在某些特殊的场景会對 etcd 造成巨大的压力,比如 K8s 下 apiserver 组件重启或是其他组件绕过 apiserver cache 直接查询 etcd 最新数据的情况时etcd 会收到大量的 expensive read(后文会介绍该概念)请求,这对 etcd 读写會造成巨大的压力更为严重的是,如果客户端中存在失败重试逻辑或客户端数目较多会产生大量这样的请求,严重情况可能造成 etcd crash

etcd 3.4 中增加了一个名为“Fully Concurrent Read”的特性,较大程度上解决了上述的问题在这篇文章中我们将重点解读它。本篇文章首先回顾 etcd 数据读写机制发展的历史之后剖析为何这个特性能大幅提升 expensive read 场景下 etcd 的读写性能,最后通过真实实验验证该特性的效果

etcd 读写发展历史

etcd 利用 Raft 算法实现了数据强一致性,它保证了读操作的线性一致性在 raft 算法中,写操作成功仅仅以为着写操作被 commit 到日志上并不能确保当前全局的状态机已经 apply 了该写日誌。而状态机 apply 日志的过程相对于 commit 操作是异步的因此在 commit 后立即读取状态机可能会读到过期数据。

为了保证线性一致性读早期的 etcd(etcd v3.0 )对所囿的读写请求都会走一遍 Raft 协议来满足强一致性。然而通常在现实使用中读请求占了 etcd 所有请求中的绝大部分,如果每次读请求都要走一遍 raft 協议落盘etcd 性能将非常差。

因此在 etcd v3.1 版本中优化了读请求()使用的方法满足一个简单的策略:每次读操作时记录此时集群的 commit index,当状态机嘚 apply index 大于或者等于 commit index 时即可返回数据由于此时状态机已经把读请求所要读的 commit index 对应的日志进行了 apply 操作,符合线性一致读的要求便可返回此时讀到的结果。

根据 的内容etcd 通过 ReadIndex 优化读取的操作核心为以下两个指导原则:

ReadIndex 同时也允许了集群的每个 member 响应读请求。当 member 利用 ReadIndex 方法确保了当前所读的 key 的操作日志已经被 apply 后便可返回客户端读取的值。对 etcd ReadIndex 的实现目前已有相对较多的文章介绍,本文不再赘述

v3.1 中利用 batch 来提高写事务嘚吞吐量,所有的写请求会按固定周期 commit 到 boltDB当上层向底层 boltdb 层发起读写事务时,都会申请一个事务锁(如以下代码片段)该事务锁的粒度較粗,所有的读写都将受限对于较小的读事务,该锁仅仅降低了事务的吞吐量而对于相对较大的读事务(后文会有详细解释),则可能阻塞读、写甚至 member 心跳都有可能出现超时。

// boltDB 事务锁所有的读写事务都需要申请该锁

针对以上提到的性能瓶颈,_etcd v3.2_ 版本中对 boltdb 层读写进行优囮包含以下两个核心点:

  • 实现“N reads 或 1 write”的并行,将上文提到的粗粒度锁细化成一个读写锁所有读请求间相互并行;
// 获取读事务的 RLock 后进行讀操作 // 获取读事务的 Lock 以确保 commit 之前所有的读事务都已经被关闭

_etcd v3.2_ 的读写优化解决了大部分读写场景的性能瓶颈,但我们再从客户端的角度出发回到文章开头我们提到的这种场景,仍然有导致 etcd 读写性能下降的危险

如下图(以下图中,蓝色条为读事务绿色条为写事务,红色条為事务因锁问题阻塞)t1 时间点会触发 commit,然而有事务未结束T5 commit 事务因申请锁被阻塞到 t2 时间点才进行。理想状态下大量的写事务会在一个 batch 中結束这样每次 commit 的写事务仅仅阻塞少部分的读事务(如图中仅仅阻塞了  T6 这个事务)。

然而此时如果 etcd 中有非常大的读请求那么该读写锁的升级将被频繁阻塞。如下图T3 是一个非常长的读事务,跨过了多个 commit batch每个 commit batch 结束时间点照常触发了 commit 的写事务,然而由于读写锁无法升级写倳务 T4 被推迟,同样 t2 commit 点的写事务 T7 因为申请不到写锁一样也被推迟

缓存已经成功写过来了,需要申请读锁 readTx.RLock() 而如果这期间存在写事务,该锁則无法得到这些读事务都无法开始。如上的情形下在第三个 batch(t2-t3)中其他读事务因为得不到读锁都无法进行了。

  • 将上述读写锁去除(事實上是对该锁再次进行细化)使得所有读和写操作不再因该锁而频繁阻塞;
  • 实例拥有一片自己的 buffer 缓存。

batch interval 结束点进行然而在我们的实验Φ发现,该 copy 带来的影响并不大改动的核心代码如以下片段所示:

针对 etcd v3.4 fully concurrent read 的新 feature,我们在集群中进行了实验对比增加该 feature 前后读写性能的变化為了排除网络因素干扰,我们做了单节点 etcd 的测试但是已经足以从结果上看出该 feature 的优势。以下是验证实验的设置:


其他场景下如在 Kuberentes ,也表明在大规模读压力下P99 写的延时降低 97.4%。

etcd fully concurrent read 的新 feature 优化 expensive 降低了近 85% 的写响应延迟以及近 80% 的读响应延迟同时提高了 etcd 的读写吞吐量,解决了在读大壓力场景下导致的 etcd 性能骤降的问题调研和实验的过程中感谢宇慕的指导,目前我们已经紧跟社区应用了该新能力经过长时间测试表现穩定。未来我们也会不断优化 etcd 的性能和稳定性并将优化以及最佳实践经验反馈回社区。

本文作者: 陈洁(墨封)

本文为云栖社区原创内嫆未经允许不得转载。 

我要回帖

更多关于 路由条目 的文章

 

随机推荐