<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title>存储与分布式 - 分类 - 星河拾贝录</title><link>https://blog.liubang.cc/categories/%E5%AD%98%E5%82%A8%E4%B8%8E%E5%88%86%E5%B8%83%E5%BC%8F/</link><description>存储与分布式 - 分类 - 星河拾贝录</description><generator>Hugo -- gohugo.io</generator><language>zh-CN</language><managingEditor>it.liubang@gmail.com (liubang)</managingEditor><webMaster>it.liubang@gmail.com (liubang)</webMaster><copyright>Copyright © 2019-2026 LiuBang. All Rights Reserved.</copyright><lastBuildDate>Wed, 01 Jan 2025 00:00:00 +0000</lastBuildDate><atom:link href="https://blog.liubang.cc/categories/%E5%AD%98%E5%82%A8%E4%B8%8E%E5%88%86%E5%B8%83%E5%BC%8F/" rel="self" type="application/rss+xml"/><item><title>BloomFilter中的数学推导</title><link>https://blog.liubang.cc/posts/storage/2025-01-01-bloomfilter%E4%B8%AD%E7%9A%84%E6%95%B0%E5%AD%A6%E6%8E%A8%E5%AF%BC/</link><pubDate>Wed, 01 Jan 2025 00:00:00 +0000</pubDate><author><name>liubang</name></author><guid>https://blog.liubang.cc/posts/storage/2025-01-01-bloomfilter%E4%B8%AD%E7%9A%84%E6%95%B0%E5%AD%A6%E6%8E%A8%E5%AF%BC/</guid><description><![CDATA[<h2 id="false-positive-rate" class="headerLink">
    <a href="#false-positive-rate" class="header-mark"></a>False Positive Rate</h2><p><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>m</mi></mrow><annotation encoding="application/x-tex">m</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">m</span></span></span></span>: 表示 Bloom Filter bit array 的长度;<br>
<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>k</mi></mrow><annotation encoding="application/x-tex">k</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span></span></span></span>: 表示 hash 函数个数;<br>
<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span>: 表示插入元素的个数;</p>
<p>假设 hash 函数以等概率选择 bit array 的下标，那么某次 hash 后，某个特定 bit 位未被设置为 1 的概率为 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>1</mn><mo>−</mo><mfrac><mn>1</mn><mi>m</mi></mfrac></mrow><annotation encoding="application/x-tex">1 - \frac{1}{m}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.1901em;vertical-align:-0.345em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8451em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span>。经过 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>k</mi></mrow><annotation encoding="application/x-tex">k</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span></span></span></span> 个 hash 函数之后，该 bit 位仍未被设置为 1 的概率为:</p>
<span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><msup><mrow><mo fence="true">(</mo><mn>1</mn><mo>−</mo><mfrac><mn>1</mn><mi>m</mi></mfrac><mo fence="true">)</mo></mrow><mi>k</mi></msup></mrow><annotation encoding="application/x-tex">
\left(1 - \frac{1}{m}\right)^k
</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:2.639em;vertical-align:-0.95em;"></span><span class="minner"><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size3">(</span></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3214em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">m</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.686em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size3">)</span></span></span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:1.689em;"><span style="top:-3.9029em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span></span></span></span></span></span></span></span></span></span></span></span><p>在插入 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span> 个元素之后，某个 bit 位仍然没有被设置为 1 的概率为:</p>]]></description></item><item><title>LevelDB 源码阅读之 Compaction</title><link>https://blog.liubang.cc/posts/storage/2021-01-12-leveldb%E6%BA%90%E7%A0%81%E9%98%85%E8%AF%BB%E4%B9%8Bcompaction/</link><pubDate>Tue, 12 Jan 2021 00:00:00 +0000</pubDate><author><name>liubang</name></author><guid>https://blog.liubang.cc/posts/storage/2021-01-12-leveldb%E6%BA%90%E7%A0%81%E9%98%85%E8%AF%BB%E4%B9%8Bcompaction/</guid><description><![CDATA[<h2 id="1-概览" class="headerLink">
    <a href="#1-%e6%a6%82%e8%a7%88" class="header-mark"></a>1. 概览</h2><p>要谈论 LevelDB 的 Compaction 就不得不从 LevelDB 的整个数据写入流程入手。LevelDB 的基本写入流程大致为：</p>
<ol>
<li>数据先写入到 WAL 日志中，做持久化</li>
<li>然后数据同步到<code>mutable memtable</code>中</li>
<li>当<code>mutable memtable</code>大小达到<code>Options.write_buffer_size</code>设置的大小时，就会变成<code>immutable memtable</code>，并且创建一个新的<code>mutable memtable</code></li>
<li>后台的 Compaction 线程会把<code>immutable memtable</code>dump 成 sstable 文件，并设置于 Level 0 层</li>
<li>当 Level i 达到一定条件后，就会和 Level i + 1 层的 sstable 进行合并，从而触发 Compaction 过程，并在 Level
n + 1 层生成一个新的 sstable 文件</li>
</ol>
<h2 id="2-compaction-分类" class="headerLink">
    <a href="#2-compaction-%e5%88%86%e7%b1%bb" class="header-mark"></a>2. Compaction 分类</h2><p>在 LevelDB 中，Compaction 大体上可以分为两类，分别是：</p>
<ul>
<li><code>immutable memtable compaction</code>，也叫做<strong>minor compaction</strong>，指的是将<code>immutable memtable</code>dump 到 sstable 文件的过程</li>
<li><code>sstable compaction</code>，也叫做<strong>major compaction</strong>，指的是 sstable 文件之间的合并过程</li>
</ul>
<p>而对于<code>sstable compaction</code>又可以细分为三种：</p>
<ul>
<li><code>manual compaction</code>，是指外部通过调用<code>DBImpl::CompactRange</code>接口触发的</li>
<li><code>size compaction</code>，是指程序根据每个 Level 的总文件大小通过一定规则自动触发的</li>
<li><code>seek compaction</code>，每个 sstable 文件内部维护了一个<strong>seek miss</strong>的 counter，当达到一定条件的时候，LevelDB 就认为这个文件需要 Compact</li>
</ul>
<p>从<code>DBImpl::BackgroundCompaction</code>的代码逻辑中不难看出，这些 Compaction 策略的优先级为：</p>]]></description></item><item><title>分布式协议</title><link>https://blog.liubang.cc/posts/storage/2020-05-25-%E5%88%86%E5%B8%83%E5%BC%8F%E5%8D%8F%E8%AE%AE/</link><pubDate>Mon, 25 May 2020 00:00:00 +0000</pubDate><author><name>liubang</name></author><guid>https://blog.liubang.cc/posts/storage/2020-05-25-%E5%88%86%E5%B8%83%E5%BC%8F%E5%8D%8F%E8%AE%AE/</guid><description><![CDATA[<h2 id="拜占庭将军问题" class="headerLink">
    <a href="#%e6%8b%9c%e5%8d%a0%e5%ba%ad%e5%b0%86%e5%86%9b%e9%97%ae%e9%a2%98" class="header-mark"></a>拜占庭将军问题</h2><h3 id="简介" class="headerLink">
    <a href="#%e7%ae%80%e4%bb%8b" class="header-mark"></a>简介</h3><ul>
<li>在可能存在叛军的情况下，采用合适的通讯协议，让多个将军达成共识，执行统一的作战计划</li>
<li>二忠一叛难题</li>
<li>它是分布式领域最复杂的容错模型</li>
<li>莱斯利·兰伯特（Leslie Lamport）<a href="https://www.microsoft.com/en-us/research/uploads/prod/2016/12/The-Byzantine-Generals-Problem.pdf" target="_blank" rel="noopener noreferrer">The Byzantine Generals Problem</a></li>
</ul>
<h3 id="二忠一叛难题" class="headerLink">
    <a href="#%e4%ba%8c%e5%bf%a0%e4%b8%80%e5%8f%9b%e9%9a%be%e9%a2%98" class="header-mark"></a>二忠一叛难题</h3><p><figure><a class="lightgallery" href="/images/2020-05-25/bzt1.png#center" title="" data-thumbnail="/images/2020-05-25/bzt1.png#center" data-sub-html="<h2>拜占庭将军问题：三个将军的通信场景</h2>"><img  loading="lazy" src='/images/2020-05-25/bzt1.png#center'     ></a><figcaption class="image-caption">拜占庭将军问题：三个将军的通信场景</figcaption>
</figure></p>
<p><figure><a class="lightgallery" href="/images/2020-05-25/bzt2.png#center" title="" data-thumbnail="/images/2020-05-25/bzt2.png#center" data-sub-html="<h2>叛军存在时的消息传递</h2>"><img  loading="lazy" src='/images/2020-05-25/bzt2.png#center'     ></a><figcaption class="image-caption">叛军存在时的消息传递</figcaption>
</figure></p>
<ul>
<li>总共有三个将军，其中一个作为指挥官</li>
<li>通过信使相互传递作战指令，进攻或者撤退</li>
<li>所有忠诚的将军必须执行统一的作战计划，忠诚的将军必须执行忠诚的指挥官发布的指令</li>
<li>假如 LIEUTENANT2 叛变，LIEUTENANT1 收到的作战指令就是“进攻，撤退”</li>
<li>假如 COMMANDER 叛变，LIEUTENANT1 和 LIEUTENANT2 收到的作战指令都是“进攻，撤退”</li>
</ul>
<h3 id="口信消息型解法" class="headerLink">
    <a href="#%e5%8f%a3%e4%bf%a1%e6%b6%88%e6%81%af%e5%9e%8b%e8%a7%a3%e6%b3%95" class="header-mark"></a>口信消息型解法</h3><ul>
<li>叛变人数为 m 需要已知</li>
<li>则所有参与者的人数至少为 3m+1</li>
<li>第一轮由指挥官发送作战指令</li>
<li>第二轮由各位将军相互发送指令</li>
<li>收到指令的将军按照少数服从多数的原则执行指令</li>
<li>按照这个公式，前面的例子叛军为 1 人的情况，则需要 1 个指挥官和 3 个将军</li>
</ul>
<p><figure><a class="lightgallery" href="/images/2020-05-25/bzt3.png#center" title="" data-thumbnail="/images/2020-05-25/bzt3.png#center" data-sub-html="<h2>将军叛变时的共识过程</h2>"><img  loading="lazy" src='/images/2020-05-25/bzt3.png#center'     ></a><figcaption class="image-caption">将军叛变时的共识过程</figcaption>
</figure></p>
<p>假如 LIEUTENANT3 叛变了，那么首先指挥官向各位将军发送“进攻”的指令，由于 3 号将军叛变了，所以最终 1 号将军收到的指令是 2 个进攻，1 个撤退，2 号将军同样收到 2 个进攻，1 个撤退，这样忠诚的将军将会执行一致的指令</p>
<p><figure><a class="lightgallery" href="/images/2020-05-25/bzt4.png#center" title="" data-thumbnail="/images/2020-05-25/bzt4.png#center" data-sub-html="<h2>指挥官叛变时的共识过程</h2>"><img  loading="lazy" src='/images/2020-05-25/bzt4.png#center'     ></a><figcaption class="image-caption">指挥官叛变时的共识过程</figcaption>
</figure></p>
<p>假如 COMMANDER 叛变了，分别向 1 号将军发送了“进攻”，向 2 号将军发送了“撤退”，向 3 号将军发送“进攻”，那么通过第二轮的协商后，1，2，3 号将军得到的指令都是“进攻，进攻，撤退”，这样按照少数服从多数的原则，忠诚的将军最终执行了一致的作战指令。</p>]]></description></item></channel></rss>