blob: 1f44613de499b8d8ce9783a2f89581304efcece7 [file] [log] [blame]
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Pegasus | Backup Request</title>
<link rel="stylesheet" href="/assets/css/app.css">
<link rel="shortcut icon" href="/assets/images/favicon.ico">
<link href="https://cdn.bootcdn.net/ajax/libs/tailwindcss/1.8.10/utilities.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/docsearch.js@2/dist/cdn/docsearch.min.css" />
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/font-awesome/5.13.0/js/all.min.js"></script>
<!-- Begin Jekyll SEO tag v2.8.0 -->
<title>Backup Request | Pegasus</title>
<meta name="generator" content="Jekyll v4.2.2" />
<meta property="og:title" content="Backup Request" />
<meta property="og:locale" content="en_US" />
<meta name="description" content="背景 在当前的Pegasus实现中,由于向secondary读取会导致不一致的情况发生,所以目前Pegasus仅仅支持对primary副本的读取。但是在某些情况下(例如:负载均衡、热点写入等)经常会导致primary不稳定。所以我们希望在primary不稳定时能够读取secondary,通过牺牲部分强一致性来降低读请求的长尾并提高系统的可用性。backup request便是用来实现此功能的。" />
<meta property="og:description" content="背景 在当前的Pegasus实现中,由于向secondary读取会导致不一致的情况发生,所以目前Pegasus仅仅支持对primary副本的读取。但是在某些情况下(例如:负载均衡、热点写入等)经常会导致primary不稳定。所以我们希望在primary不稳定时能够读取secondary,通过牺牲部分强一致性来降低读请求的长尾并提高系统的可用性。backup request便是用来实现此功能的。" />
<meta property="og:site_name" content="Pegasus" />
<meta property="og:type" content="article" />
<meta property="article:published_time" content="2022-03-12T09:31:56+00:00" />
<meta name="twitter:card" content="summary" />
<meta property="twitter:title" content="Backup Request" />
<script type="application/ld+json">
{"@context":"https://schema.org","@type":"BlogPosting","dateModified":"2022-03-12T09:31:56+00:00","datePublished":"2022-03-12T09:31:56+00:00","description":"背景 在当前的Pegasus实现中,由于向secondary读取会导致不一致的情况发生,所以目前Pegasus仅仅支持对primary副本的读取。但是在某些情况下(例如:负载均衡、热点写入等)经常会导致primary不稳定。所以我们希望在primary不稳定时能够读取secondary,通过牺牲部分强一致性来降低读请求的长尾并提高系统的可用性。backup request便是用来实现此功能的。","headline":"Backup Request","mainEntityOfPage":{"@type":"WebPage","@id":"/administration/backup-request"},"url":"/administration/backup-request"}</script>
<!-- End Jekyll SEO tag -->
</head>
<body>
<div class="dashboard is-full-height">
<!-- left panel -->
<div class="dashboard-panel is-medium is-hidden-mobile pl-0">
<div class="dashboard-panel-header has-text-centered">
<a href="/">
<img src="/assets/images/pegasus-logo-inv.png" style="width: 80%;">
</a>
</div>
<div class="dashboard-panel-main is-scrollable pl-6">
<aside class="menu">
<p class="menu-label">Pegasus产品文档</p>
<ul class="menu-list">
<li>
<a href="/docs/downloads"
class="">
下载
</a>
</li>
</ul>
<p class="menu-label">编译构建</p>
<ul class="menu-list">
<li>
<a href="/docs/build/compile-by-docker"
class="">
使用Docker完成编译(推荐)
</a>
</li>
<li>
<a href="/docs/build/compile-from-source"
class="">
从源码编译
</a>
</li>
</ul>
<p class="menu-label">客户端库</p>
<ul class="menu-list">
<li>
<a href="/clients/java-client"
class="">
Java客户端
</a>
</li>
<li>
<a href="/clients/cpp-client"
class="">
C++客户端
</a>
</li>
<li>
<a href="https://github.com/XiaoMi/pegasus-go-client"
class="">
Golang客户端
</a>
</li>
<li>
<a href="/clients/python2-client"
class="">
Python2客户端
</a>
</li>
<li>
<a href="/clients/python3-client"
class="">
Python3客户端
</a>
</li>
<li>
<a href="/clients/node-client"
class="">
NodeJS客户端
</a>
</li>
<li>
<a href="/clients/scala-client"
class="">
Scala客户端
</a>
</li>
</ul>
<p class="menu-label">生态工具</p>
<ul class="menu-list">
<li>
<a href="/docs/tools/shell"
class="">
Pegasus Shell 工具
</a>
</li>
<li>
<a href="https://github.com/pegasus-kv/admin-cli"
class="">
集群管理命令行
</a>
</li>
<li>
<a href="https://github.com/pegasus-kv/pegic"
class="">
数据访问命令行
</a>
</li>
</ul>
<p class="menu-label">用户接口</p>
<ul class="menu-list">
<li>
<a href="/api/ttl"
class="">
TTL
</a>
</li>
<li>
<a href="/api/single-atomic"
class="">
单行原子操作
</a>
</li>
<li>
<a href="/api/redis"
class="">
Redis适配
</a>
</li>
<li>
<a href="/api/geo"
class="">
GEO支持
</a>
</li>
<li>
<a href="/api/http"
class="">
HTTP接口
</a>
</li>
</ul>
<p class="menu-label">高效运维</p>
<ul class="menu-list">
<li>
<a href="/administration/deployment"
class="">
集群部署
</a>
</li>
<li>
<a href="/administration/config"
class="">
配置说明
</a>
</li>
<li>
<a href="/administration/rebalance"
class="">
负载均衡
</a>
</li>
<li>
<a href="/administration/monitoring"
class="">
可视化监控
</a>
</li>
<li>
<a href="/administration/rolling-update"
class="">
集群升级
</a>
</li>
<li>
<a href="/administration/scale-in-out"
class="">
集群扩容缩容
</a>
</li>
<li>
<a href="/administration/resource-management"
class="">
资源管理
</a>
</li>
<li>
<a href="/administration/cold-backup"
class="">
冷备份
</a>
</li>
<li>
<a href="/administration/meta-recovery"
class="">
元数据恢复
</a>
</li>
<li>
<a href="/administration/replica-recovery"
class="">
Replica数据恢复
</a>
</li>
<li>
<a href="/administration/zk-migration"
class="">
Zookeeper迁移
</a>
</li>
<li>
<a href="/administration/table-migration"
class="">
Table迁移
</a>
</li>
<li>
<a href="/administration/table-soft-delete"
class="">
Table软删除
</a>
</li>
<li>
<a href="/administration/table-env"
class="">
Table环境变量
</a>
</li>
<li>
<a href="/administration/remote-commands"
class="">
远程命令
</a>
</li>
<li>
<a href="/administration/partition-split"
class="">
Partition-Split
</a>
</li>
<li>
<a href="/administration/duplication"
class="">
跨机房同步
</a>
</li>
<li>
<a href="/administration/compression"
class="">
数据压缩
</a>
</li>
<li>
<a href="/administration/throttling"
class="">
流量控制
</a>
</li>
<li>
<a href="/administration/experiences"
class="">
运维经验
</a>
</li>
<li>
<a href="/administration/manual-compact"
class="">
Manual Compact功能
</a>
</li>
<li>
<a href="/administration/usage-scenario"
class="">
Usage Scenario功能
</a>
</li>
<li>
<a href="/administration/bad-disk"
class="">
坏盘检修
</a>
</li>
<li>
<a href="/administration/whitelist"
class="">
白名单
</a>
</li>
<li>
<a href="/administration/backup-request"
class="is-active">
Backup Request
</a>
</li>
<li>
<a href="/administration/hotspot-detection"
class="">
热点检测
</a>
</li>
</ul>
</aside>
</div>
</div>
<!-- main section -->
<div class="dashboard-main is-scrollable">
<nav class="navbar is-hidden-desktop">
<div class="navbar-brand">
<a href="/" class="navbar-item">
<!-- Pegasus Icon -->
<img src="/assets/images/pegasus-square.png">
</a>
<div class="navbar-item">
<!--A simple language switch button that only supports zh and en.-->
<!--IF its language is zh, then switches to en.-->
<a class="button is-light is-outlined is-inverted" href="/en/administration/backup-request"><strong>En</strong></a>
</div>
<a role="button" class="navbar-burger burger" aria-label="menu" aria-expanded="false" data-target="navMenu">
<!-- Appears in mobile mode only -->
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
</a>
</div>
<div class="navbar-menu" id="navMenu">
<div class="navbar-end">
<!--dropdown-->
<div class="navbar-item has-dropdown is-hoverable">
<a href=""
class="navbar-link ">
<span>
Pegasus产品文档
</span>
</a>
<div class="navbar-dropdown">
<a href="/docs/downloads"
class="navbar-item ">
下载
</a>
</div>
</div>
<!--dropdown-->
<div class="navbar-item has-dropdown is-hoverable">
<a href=""
class="navbar-link ">
<span>
编译构建
</span>
</a>
<div class="navbar-dropdown">
<a href="/docs/build/compile-by-docker"
class="navbar-item ">
使用Docker完成编译(推荐)
</a>
<a href="/docs/build/compile-from-source"
class="navbar-item ">
从源码编译
</a>
</div>
</div>
<!--dropdown-->
<div class="navbar-item has-dropdown is-hoverable">
<a href=""
class="navbar-link ">
<span>
客户端库
</span>
</a>
<div class="navbar-dropdown">
<a href="/clients/java-client"
class="navbar-item ">
Java客户端
</a>
<a href="/clients/cpp-client"
class="navbar-item ">
C++客户端
</a>
<a href="https://github.com/XiaoMi/pegasus-go-client"
class="navbar-item ">
Golang客户端
</a>
<a href="/clients/python2-client"
class="navbar-item ">
Python2客户端
</a>
<a href="/clients/python3-client"
class="navbar-item ">
Python3客户端
</a>
<a href="/clients/node-client"
class="navbar-item ">
NodeJS客户端
</a>
<a href="/clients/scala-client"
class="navbar-item ">
Scala客户端
</a>
</div>
</div>
<!--dropdown-->
<div class="navbar-item has-dropdown is-hoverable">
<a href=""
class="navbar-link ">
<span>
生态工具
</span>
</a>
<div class="navbar-dropdown">
<a href="/docs/tools/shell"
class="navbar-item ">
Pegasus Shell 工具
</a>
<a href="https://github.com/pegasus-kv/admin-cli"
class="navbar-item ">
集群管理命令行
</a>
<a href="https://github.com/pegasus-kv/pegic"
class="navbar-item ">
数据访问命令行
</a>
</div>
</div>
<!--dropdown-->
<div class="navbar-item has-dropdown is-hoverable">
<a href=""
class="navbar-link ">
<span>
用户接口
</span>
</a>
<div class="navbar-dropdown">
<a href="/api/ttl"
class="navbar-item ">
TTL
</a>
<a href="/api/single-atomic"
class="navbar-item ">
单行原子操作
</a>
<a href="/api/redis"
class="navbar-item ">
Redis适配
</a>
<a href="/api/geo"
class="navbar-item ">
GEO支持
</a>
<a href="/api/http"
class="navbar-item ">
HTTP接口
</a>
</div>
</div>
<!--dropdown-->
<div class="navbar-item has-dropdown is-hoverable">
<a href=""
class="navbar-link ">
<span>
高效运维
</span>
</a>
<div class="navbar-dropdown">
<a href="/administration/deployment"
class="navbar-item ">
集群部署
</a>
<a href="/administration/config"
class="navbar-item ">
配置说明
</a>
<a href="/administration/rebalance"
class="navbar-item ">
负载均衡
</a>
<a href="/administration/monitoring"
class="navbar-item ">
可视化监控
</a>
<a href="/administration/rolling-update"
class="navbar-item ">
集群升级
</a>
<a href="/administration/scale-in-out"
class="navbar-item ">
集群扩容缩容
</a>
<a href="/administration/resource-management"
class="navbar-item ">
资源管理
</a>
<a href="/administration/cold-backup"
class="navbar-item ">
冷备份
</a>
<a href="/administration/meta-recovery"
class="navbar-item ">
元数据恢复
</a>
<a href="/administration/replica-recovery"
class="navbar-item ">
Replica数据恢复
</a>
<a href="/administration/zk-migration"
class="navbar-item ">
Zookeeper迁移
</a>
<a href="/administration/table-migration"
class="navbar-item ">
Table迁移
</a>
<a href="/administration/table-soft-delete"
class="navbar-item ">
Table软删除
</a>
<a href="/administration/table-env"
class="navbar-item ">
Table环境变量
</a>
<a href="/administration/remote-commands"
class="navbar-item ">
远程命令
</a>
<a href="/administration/partition-split"
class="navbar-item ">
Partition-Split
</a>
<a href="/administration/duplication"
class="navbar-item ">
跨机房同步
</a>
<a href="/administration/compression"
class="navbar-item ">
数据压缩
</a>
<a href="/administration/throttling"
class="navbar-item ">
流量控制
</a>
<a href="/administration/experiences"
class="navbar-item ">
运维经验
</a>
<a href="/administration/manual-compact"
class="navbar-item ">
Manual Compact功能
</a>
<a href="/administration/usage-scenario"
class="navbar-item ">
Usage Scenario功能
</a>
<a href="/administration/bad-disk"
class="navbar-item ">
坏盘检修
</a>
<a href="/administration/whitelist"
class="navbar-item ">
白名单
</a>
<a href="/administration/backup-request"
class="navbar-item is-active">
Backup Request
</a>
<a href="/administration/hotspot-detection"
class="navbar-item ">
热点检测
</a>
</div>
</div>
</div>
</div>
</nav>
<nav class="navbar is-hidden-mobile">
<div class="navbar-start w-full">
<div class="navbar-item pl-0 w-full">
<!--TODO(wutao): Given the limitation of docsearch that couldn't handle multiple input,
I make searchbox only shown in desktop. Fix this issue when docsearch.js v3 released.
Related issue: https://github.com/algolia/docsearch/issues/230-->
<div class="navbar-searchbox w-full bg-gray-200">
<div class="field">
<div class="control has-icons-right">
<input class="input searchbox-input focus:placeholder-transparent"
type="text" placeholder="Search the docs">
<span class="icon is-right">
<i class="fas fa-search searchbox-icon"></i>
</span>
</div>
</div>
</div>
</div>
</div>
<div class="navbar-end">
<div class="navbar-item">
<!--A simple language switch button that only supports zh and en.-->
<!--IF its language is zh, then switches to en.-->
<a class="button is-light is-outlined is-inverted" href="/en/administration/backup-request"><strong>En</strong></a>
</div>
</div>
</nav>
<section class="hero is-info lg:mr-3">
<div class="hero-body">
<p class="title is-size-2 is-centered">Backup Request</p>
</div>
</section>
<section class="section" style="padding-top: 2rem;">
<div class="content">
<h1 id="背景">背景</h1>
<p>在当前的Pegasus实现中,由于向secondary读取会导致不一致的情况发生,所以目前Pegasus仅仅支持对primary副本的读取。但是在某些情况下(例如:负载均衡、热点写入等)经常会导致primary不稳定。所以我们希望在primary不稳定时能够读取secondary,通过牺牲部分强一致性来降低读请求的长尾并提高系统的可用性。backup request便是用来实现此功能的。</p>
<h1 id="设计实现">设计实现</h1>
<p>backup reqeust的实现原理比较简单:对于读操作(目前写操作不支持backup request),当client向primary发送请求后,如果经过一段时间延时(通常是p999)其response仍然没有返回,则随机选择一台secondary并向其发送backup request。最后获取最快返回来的response进行处理。</p>
<p>这里发送secondary请求的延时我们建议选择p999,因为backup request操作是用来实现消除长尾的,并不是提升集群性能的。如果将该值设置过低,则会由于backup request的请求量过大而导致集群压力增大(假设选择p50作为其延时,这样便会有50%的请求向secondary发送请求,系统负载便会增大50%)。</p>
<h1 id="如何使用">如何使用</h1>
<p>在Pegasus java client v2.0.0中,我们增加了一个接口,通过该接口可以打开某个表的backup reqeust功能。其实现如下:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="nc">PegasusTableInterface</span> <span class="nf">openTable</span><span class="o">(</span><span class="nc">String</span> <span class="n">tableName</span><span class="o">,</span> <span class="kt">int</span> <span class="n">backupRequestDelayMs</span><span class="o">)</span> <span class="kd">throws</span> <span class="nc">PException</span><span class="o">;</span>
</code></pre></div></div>
<p>相比于老版本的<code class="language-plaintext highlighter-rouge">openTable</code>接口,我们增加了一个<code class="language-plaintext highlighter-rouge">backupRequestDelayMs</code>参数。这个参数便是上文所指的时延,即:向primary发送请求,如果过了<code class="language-plaintext highlighter-rouge">backupRequestDelayMs</code>毫秒response仍没有返回,则向secondary发送backup request。需要注意的是,<code class="language-plaintext highlighter-rouge">backupRequestDelayMs &lt;= 0</code>代表禁用backup reqeust功能。</p>
<p>另外在老版本的<code class="language-plaintext highlighter-rouge">openTable</code>接口中,backup request功能默认是关闭的。</p>
<h1 id="性能测试">性能测试</h1>
<p>下面表格里展示了是否打开backup request的性能对比,这里我们选取了未打开backup request时读请求的p999时间作为backup request的delay时间(138ms)。数据显示,打开backup request之后get请求的p999时延<strong>基本没有变化</strong>,而p9999时延却有了<strong>数倍的降低</strong></p>
<p>另外,由于delay时间设置的是p999时间,大约1000个请求里只有1个请求会发送backup request,因此额外请求量(也就是开启backup request的额外开销)比例在0.1%左右。依此类推,若想要降低P999时延,则可以将 <code class="language-plaintext highlighter-rouge">backupRequestDelayMs</code> 设置为P99延迟,由此会增加1%的额外读流量。</p>
<table>
<thead>
<tr>
<th>test case</th>
<th>enable backup request</th>
<th>read p9999</th>
</tr>
</thead>
<tbody>
<tr>
<td>3-clients 15-threads</td>
<td>no</td>
<td>988671</td>
</tr>
<tr>
<td>3-clients 15-threads</td>
<td>yes</td>
<td>153599</td>
</tr>
</tbody>
</table>
</div>
</section>
<footer class="footer">
<div class="container">
<div class="content is-small has-text-centered">
<div style="margin-bottom: 20px;">
<a href="http://incubator.apache.org"><img src="/assets/images/egg-logo.png"
alt="Apache Incubator"/></a>
</div>
Copyright &copy; 2020 <a href="http://www.apache.org">The Apache Software Foundation</a>.
Licensed under the <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache License, Version
2.0</a>.
<br><br>
Apache Pegasus is an effort undergoing incubation at The Apache Software Foundation (ASF),
sponsored by the Apache Incubator. Incubation is required of all newly accepted projects
until a further review indicates that the infrastructure, communications, and decision making process
have stabilized in a manner consistent with other successful ASF projects. While incubation status is
not necessarily a reflection of the completeness or stability of the code, it does indicate that the
project has yet to be fully endorsed by the ASF.
</div>
</div>
</footer>
</div>
<!-- right panel -->
<div class="dashboard-panel is-small is-scrollable is-hidden-mobile">
<p class="menu-label">
<span class="icon">
<i class="fa fa-bars" aria-hidden="true"></i>
</span>
本页导航
</p>
<ul class="menu-list">
<li><a href="#背景">背景</a></li>
<li><a href="#设计实现">设计实现</a></li>
<li><a href="#如何使用">如何使用</a></li>
<li><a href="#性能测试">性能测试</a></li>
</ul>
</div>
</div>
<script src="/assets/js/app.js" type="text/javascript"></script>
<script src="https://cdn.jsdelivr.net/npm/docsearch.js@2/dist/cdn/docsearch.min.js"></script>
<script>
docsearch({
indexName: 'apache_pegasus',
apiKey: '676624c2d6dc00808d3b7cf6724fc3c8',
inputSelector: '.searchbox-input',
debug: true,
});
</script>
</body>
</html>