mirror of
https://github.com/zhwei820/learn.lianglianglee.com.git
synced 2025-09-27 05:36:42 +08:00
372 lines
33 KiB
HTML
372 lines
33 KiB
HTML
<!DOCTYPE html>
|
||
<!-- saved from url=(0046)https://kaiiiz.github.io/hexo-theme-book-demo/ -->
|
||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||
<head>
|
||
<head>
|
||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=no">
|
||
<link rel="icon" href="/static/favicon.png">
|
||
<title>46 SSD硬盘(上):如何完成性能优化的KPI?.md.html</title>
|
||
<!-- Spectre.css framework -->
|
||
<link rel="stylesheet" href="/static/index.css">
|
||
<!-- theme css & js -->
|
||
<meta name="generator" content="Hexo 4.2.0">
|
||
</head>
|
||
<body>
|
||
<div class="book-container">
|
||
<div class="book-sidebar">
|
||
<div class="book-brand">
|
||
<a href="/">
|
||
<img src="/static/favicon.png">
|
||
<span>技术文章摘抄</span>
|
||
</a>
|
||
</div>
|
||
<div class="book-menu uncollapsible">
|
||
<ul class="uncollapsible">
|
||
<li><a href="/" class="current-tab">首页</a></li>
|
||
</ul>
|
||
<ul class="uncollapsible">
|
||
<li><a href="../">上一级</a></li>
|
||
</ul>
|
||
<ul class="uncollapsible">
|
||
<li>
|
||
<a href="/专栏/深入浅出计算机组成原理/00 开篇词 为什么你需要学习计算机组成原理?.md.html">00 开篇词 为什么你需要学习计算机组成原理?</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/深入浅出计算机组成原理/01 冯·诺依曼体系结构:计算机组成的金字塔.md.html">01 冯·诺依曼体系结构:计算机组成的金字塔</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/深入浅出计算机组成原理/02 给你一张知识地图,计算机组成原理应该这么学.md.html">02 给你一张知识地图,计算机组成原理应该这么学</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/深入浅出计算机组成原理/03 通过你的CPU主频,我们来谈谈“性能”究竟是什么?.md.html">03 通过你的CPU主频,我们来谈谈“性能”究竟是什么?</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/深入浅出计算机组成原理/04 穿越功耗墙,我们该从哪些方面提升“性能”?.md.html">04 穿越功耗墙,我们该从哪些方面提升“性能”?</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/深入浅出计算机组成原理/05 计算机指令:让我们试试用纸带编程.md.html">05 计算机指令:让我们试试用纸带编程</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/深入浅出计算机组成原理/06 指令跳转:原来if...else就是goto.md.html">06 指令跳转:原来if...else就是goto</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/深入浅出计算机组成原理/07 函数调用:为什么会发生stack overflow?.md.html">07 函数调用:为什么会发生stack overflow?</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/深入浅出计算机组成原理/08 ELF和静态链接:为什么程序无法同时在Linux和Windows下运行?.md.html">08 ELF和静态链接:为什么程序无法同时在Linux和Windows下运行?</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/深入浅出计算机组成原理/09 程序装载:“640K内存”真的不够用么?.md.html">09 程序装载:“640K内存”真的不够用么?</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/深入浅出计算机组成原理/10 动态链接:程序内部的“共享单车”.md.html">10 动态链接:程序内部的“共享单车”</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/深入浅出计算机组成原理/11 二进制编码:“手持两把锟斤拷,口中疾呼烫烫烫”?.md.html">11 二进制编码:“手持两把锟斤拷,口中疾呼烫烫烫”?</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/深入浅出计算机组成原理/12 理解电路:从电报机到门电路,我们如何做到“千里传信”?.md.html">12 理解电路:从电报机到门电路,我们如何做到“千里传信”?</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/深入浅出计算机组成原理/13 加法器:如何像搭乐高一样搭电路(上)?.md.html">13 加法器:如何像搭乐高一样搭电路(上)?</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/深入浅出计算机组成原理/14 乘法器:如何像搭乐高一样搭电路(下)?.md.html">14 乘法器:如何像搭乐高一样搭电路(下)?</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/深入浅出计算机组成原理/15 浮点数和定点数(上):怎么用有限的Bit表示尽可能多的信息?.md.html">15 浮点数和定点数(上):怎么用有限的Bit表示尽可能多的信息?</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/深入浅出计算机组成原理/16 浮点数和定点数(下):深入理解浮点数到底有什么用?.md.html">16 浮点数和定点数(下):深入理解浮点数到底有什么用?</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/深入浅出计算机组成原理/17 建立数据通路(上):指令加运算=CPU.md.html">17 建立数据通路(上):指令加运算=CPU</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/深入浅出计算机组成原理/18 建立数据通路(中):指令加运算=CPU.md.html">18 建立数据通路(中):指令加运算=CPU</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/深入浅出计算机组成原理/19 建立数据通路(下):指令加运算=CPU.md.html">19 建立数据通路(下):指令加运算=CPU</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/深入浅出计算机组成原理/20 面向流水线的指令设计(上):一心多用的现代CPU.md.html">20 面向流水线的指令设计(上):一心多用的现代CPU</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/深入浅出计算机组成原理/21 面向流水线的指令设计(下):奔腾4是怎么失败的?.md.html">21 面向流水线的指令设计(下):奔腾4是怎么失败的?</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/深入浅出计算机组成原理/22 冒险和预测(一):hazard是“危”也是“机”.md.html">22 冒险和预测(一):hazard是“危”也是“机”</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/深入浅出计算机组成原理/23 冒险和预测(二):流水线里的接力赛.md.html">23 冒险和预测(二):流水线里的接力赛</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/深入浅出计算机组成原理/24 冒险和预测(三):CPU里的“线程池”.md.html">24 冒险和预测(三):CPU里的“线程池”</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/深入浅出计算机组成原理/25 冒险和预测(四):今天下雨了,明天还会下雨么?.md.html">25 冒险和预测(四):今天下雨了,明天还会下雨么?</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/深入浅出计算机组成原理/26 Superscalar和VLIW:如何让CPU的吞吐率超过1?.md.html">26 Superscalar和VLIW:如何让CPU的吞吐率超过1?</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/深入浅出计算机组成原理/27 SIMD:如何加速矩阵乘法?.md.html">27 SIMD:如何加速矩阵乘法?</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/深入浅出计算机组成原理/28 异常和中断:程序出错了怎么办?.md.html">28 异常和中断:程序出错了怎么办?</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/深入浅出计算机组成原理/29 CISC和RISC:为什么手机芯片都是ARM?.md.html">29 CISC和RISC:为什么手机芯片都是ARM?</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/深入浅出计算机组成原理/30 GPU(上):为什么玩游戏需要使用GPU?.md.html">30 GPU(上):为什么玩游戏需要使用GPU?</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/深入浅出计算机组成原理/31 GPU(下):为什么深度学习需要使用GPU?.md.html">31 GPU(下):为什么深度学习需要使用GPU?</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/深入浅出计算机组成原理/32 FPGA、ASIC和TPU(上):计算机体系结构的黄金时代.md.html">32 FPGA、ASIC和TPU(上):计算机体系结构的黄金时代</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/深入浅出计算机组成原理/33 解读TPU:设计和拆解一块ASIC芯片.md.html">33 解读TPU:设计和拆解一块ASIC芯片</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/深入浅出计算机组成原理/34 理解虚拟机:你在云上拿到的计算机是什么样的?.md.html">34 理解虚拟机:你在云上拿到的计算机是什么样的?</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/深入浅出计算机组成原理/35 存储器层次结构全景:数据存储的大金字塔长什么样?.md.html">35 存储器层次结构全景:数据存储的大金字塔长什么样?</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/深入浅出计算机组成原理/36 局部性原理:数据库性能跟不上,加个缓存就好了?.md.html">36 局部性原理:数据库性能跟不上,加个缓存就好了?</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/深入浅出计算机组成原理/37 理解CPU Cache(上):“4毫秒”究竟值多少钱?.md.html">37 理解CPU Cache(上):“4毫秒”究竟值多少钱?</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/深入浅出计算机组成原理/38 高速缓存(下):你确定你的数据更新了么?.md.html">38 高速缓存(下):你确定你的数据更新了么?</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/深入浅出计算机组成原理/39 MESI协议:如何让多核CPU的高速缓存保持一致?.md.html">39 MESI协议:如何让多核CPU的高速缓存保持一致?</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/深入浅出计算机组成原理/40 理解内存(上):虚拟内存和内存保护是什么?.md.html">40 理解内存(上):虚拟内存和内存保护是什么?</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/深入浅出计算机组成原理/41 理解内存(下):解析TLB和内存保护.md.html">41 理解内存(下):解析TLB和内存保护</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/深入浅出计算机组成原理/42 总线:计算机内部的高速公路.md.html">42 总线:计算机内部的高速公路</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/深入浅出计算机组成原理/43 输入输出设备:我们并不是只能用灯泡显示“0”和“1”.md.html">43 输入输出设备:我们并不是只能用灯泡显示“0”和“1”</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/深入浅出计算机组成原理/44 理解IO_WAIT:IO性能到底是怎么回事儿?.md.html">44 理解IO_WAIT:IO性能到底是怎么回事儿?</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/深入浅出计算机组成原理/45 机械硬盘:Google早期用过的“黑科技”.md.html">45 机械硬盘:Google早期用过的“黑科技”</a>
|
||
</li>
|
||
<li>
|
||
<a class="current-tab" href="/专栏/深入浅出计算机组成原理/46 SSD硬盘(上):如何完成性能优化的KPI?.md.html">46 SSD硬盘(上):如何完成性能优化的KPI?</a>
|
||
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/深入浅出计算机组成原理/47 SSD硬盘(下):如何完成性能优化的KPI?.md.html">47 SSD硬盘(下):如何完成性能优化的KPI?</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/深入浅出计算机组成原理/48 DMA:为什么Kafka这么快?.md.html">48 DMA:为什么Kafka这么快?</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/深入浅出计算机组成原理/49 数据完整性(上):硬件坏了怎么办?.md.html">49 数据完整性(上):硬件坏了怎么办?</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/深入浅出计算机组成原理/50 数据完整性(下):如何还原犯罪现场?.md.html">50 数据完整性(下):如何还原犯罪现场?</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/深入浅出计算机组成原理/51 分布式计算:如果所有人的大脑都联网会怎样?.md.html">51 分布式计算:如果所有人的大脑都联网会怎样?</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/深入浅出计算机组成原理/52 设计大型DMP系统(上):MongoDB并不是什么灵丹妙药.md.html">52 设计大型DMP系统(上):MongoDB并不是什么灵丹妙药</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/深入浅出计算机组成原理/53 设计大型DMP系统(下):SSD拯救了所有的DBA.md.html">53 设计大型DMP系统(下):SSD拯救了所有的DBA</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/深入浅出计算机组成原理/54 理解Disruptor(上):带你体会CPU高速缓存的风驰电掣.md.html">54 理解Disruptor(上):带你体会CPU高速缓存的风驰电掣</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/深入浅出计算机组成原理/55 理解Disruptor(下):不需要换挡和踩刹车的CPU,有多快?.md.html">55 理解Disruptor(下):不需要换挡和踩刹车的CPU,有多快?</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/深入浅出计算机组成原理/结束语 知也无涯,愿你也享受发现的乐趣.md.html">结束语 知也无涯,愿你也享受发现的乐趣</a>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
<div class="sidebar-toggle" onclick="sidebar_toggle()" onmouseover="add_inner()" onmouseleave="remove_inner()">
|
||
<div class="sidebar-toggle-inner"></div>
|
||
</div>
|
||
<script>
|
||
function add_inner() {
|
||
let inner = document.querySelector('.sidebar-toggle-inner')
|
||
inner.classList.add('show')
|
||
}
|
||
function remove_inner() {
|
||
let inner = document.querySelector('.sidebar-toggle-inner')
|
||
inner.classList.remove('show')
|
||
}
|
||
function sidebar_toggle() {
|
||
let sidebar_toggle = document.querySelector('.sidebar-toggle')
|
||
let sidebar = document.querySelector('.book-sidebar')
|
||
let content = document.querySelector('.off-canvas-content')
|
||
if (sidebar_toggle.classList.contains('extend')) { // show
|
||
sidebar_toggle.classList.remove('extend')
|
||
sidebar.classList.remove('hide')
|
||
content.classList.remove('extend')
|
||
} else { // hide
|
||
sidebar_toggle.classList.add('extend')
|
||
sidebar.classList.add('hide')
|
||
content.classList.add('extend')
|
||
}
|
||
}
|
||
function open_sidebar() {
|
||
let sidebar = document.querySelector('.book-sidebar')
|
||
let overlay = document.querySelector('.off-canvas-overlay')
|
||
sidebar.classList.add('show')
|
||
overlay.classList.add('show')
|
||
}
|
||
function hide_canvas() {
|
||
let sidebar = document.querySelector('.book-sidebar')
|
||
let overlay = document.querySelector('.off-canvas-overlay')
|
||
sidebar.classList.remove('show')
|
||
overlay.classList.remove('show')
|
||
}
|
||
</script>
|
||
<div class="off-canvas-content">
|
||
<div class="columns">
|
||
<div class="column col-12 col-lg-12">
|
||
<div class="book-navbar">
|
||
<!-- For Responsive Layout -->
|
||
<header class="navbar">
|
||
<section class="navbar-section">
|
||
<a onclick="open_sidebar()">
|
||
<i class="icon icon-menu"></i>
|
||
</a>
|
||
</section>
|
||
</header>
|
||
</div>
|
||
<div class="book-content" style="max-width: 960px; margin: 0 auto;
|
||
overflow-x: auto;
|
||
overflow-y: hidden;">
|
||
<div class="book-post">
|
||
<p id="tip" align="center"></p>
|
||
<div><h1>46 SSD硬盘(上):如何完成性能优化的KPI?</h1>
|
||
<p>随着 3D 垂直封装技术和 QLC 技术的出现,今年的“618”,SSD 硬盘的价格进一步大跳水,趁着这个机会,我把自己电脑上的仓库盘,从 HDD 换成了 SSD 硬盘。我的个人电脑彻底摆脱了机械硬盘。</p>
|
||
<p>随着智能手机的出现,互联网用户在 2008 年之后开始爆发性增长,大家在网上花的时间也越来越多。这也就意味着,隐藏在精美 App 和网页之后的服务端数据请求量,呈数量级的上升。</p>
|
||
<p>无论是用 10000 转的企业级机械硬盘,还是用 Short Stroking 这样的方式进一步提升 IOPS,HDD 硬盘已经满足不了我们的需求了。上面这些优化措施,无非就是,把 IOPS 从 100 提升到 300、500 也就到头了。</p>
|
||
<p>于是,SSD 硬盘在 2010 年前后,进入了主流的商业应用。我们在<a href="https://time.geekbang.org/column/article/113809">第 44 讲</a>看过,一块普通的 SSD 硬盘,可以轻松支撑 10000 乃至 20000 的 IOPS。那个时候,不少互联网公司想要完成性能优化的 KPI,最后的解决方案都变成了换 SSD 的硬盘。如果这还不够,那就换上使用 PCI Express 接口的 SSD。</p>
|
||
<p>不过,只是简单地换一下 SSD 硬盘,真的最大限度地用好了 SSD 硬盘吗?另外,即便现在 SSD 硬盘很便宜了,大部分公司的批量数据处理系统,仍然在用传统的机械硬盘,这又是为什么呢?</p>
|
||
<p>那么接下来这两讲,就请你和我一起来看一看,SSD 硬盘的工作原理,以及怎么最大化利用 SSD 的工作原理,使得访问的速度最快,硬盘的使用寿命最长。</p>
|
||
<h2>SSD 的读写原理</h2>
|
||
<p>SSD 没有像机械硬盘那样的寻道过程,所以它的随机读写都更快。我在下面列了一个表格,对比了一下 SSD 和机械硬盘的优缺点。</p>
|
||
<p><img src="assets/a53e407311293609cb0753c7889a367c.jpeg" alt="img" /></p>
|
||
<p>你会发现,不管是机械硬盘不擅长的随机读写,还是它本身已经表现不错的顺序写入,SSD 在这些方面都要比 HDD 强。不过,有一点,机械硬盘要远强于 SSD,那就是耐用性。如果我们需要频繁地重复写入删除数据,那么机械硬盘要比 SSD 性价比高很多。</p>
|
||
<p>要想知道为什么 SSD 的耐用性不太好,我们先要理解 SSD 硬盘的存储和读写原理。我们之前说过,CPU Cache 用的 SRAM 是用一个电容来存放一个比特的数据。对于 SSD 硬盘,我们也可以先简单地认为,它是由一个电容加上一个电压计组合在一起,记录了一个或者多个比特。</p>
|
||
<h3>SLC、MLC、TLC 和 QLC</h3>
|
||
<p>能够记录一个比特很容易理解。给电容里面充上电有电压的时候就是 1,给电容放电里面没有电就是 0。采用这样方式存储数据的 SSD 硬盘,我们一般称之为<strong>使用了 SLC 的颗粒</strong>,全称是 Single-Level Cell,也就是一个存储单元中只有一位数据。</p>
|
||
<p><img src="assets/0698c240459faa11254932905675dba7.jpeg" alt="img" /></p>
|
||
<p>但是,这样的方式会遇到和 CPU Cache 类似的问题,那就是,同样的面积下,能够存放下的元器件是有限的。如果只用 SLC,我们就会遇到,存储容量上不去,并且价格下不来的问题。于是呢,硬件工程师们就陆续发明了<strong>MLC</strong>(Multi-Level Cell)、<strong>TLC</strong>(Triple-Level Cell)以及<strong>QLC</strong>(Quad-Level Cell),也就是能在一个电容里面存下 2 个、3 个乃至 4 个比特。</p>
|
||
<p><img src="assets/949106cb0ca5985a47388caef6925a79.jpeg" alt="img" /></p>
|
||
<p>只有一个电容,我们怎么能够表示更多的比特呢?别忘了,这里我们还有一个电压计。4 个比特一共可以从 0000-1111 表示 16 个不同的数。那么,如果我们能往电容里面充电的时候,充上 15 个不同的电压,并且我们电压计能够区分出这 15 个不同的电压。加上电容被放空代表的 0,就能够代表从 0000-1111 这样 4 个比特了。</p>
|
||
<p>不过,要想表示 15 个不同的电压,充电和读取的时候,对于精度的要求就会更高。这会导致充电和读取的时候都更慢,所以 QLC 的 SSD 的读写速度,要比 SLC 的慢上好几倍。如果你想要知道是什么样的物理原理导致这个 QLC 更慢,可以去读一读这篇<a href="https://www.anandtech.com/show/5067/understanding-tlc-nand/2">文章</a>。</p>
|
||
<h3>P/E 擦写问题</h3>
|
||
<p>如果我们去看一看 SSD 硬盘的硬件构造,可以看到,它大概是自顶向下是这么构成的。</p>
|
||
<p><img src="assets/6ac3cfd51d39d3e3022effc7e4255e5e.jpeg" alt="img" /></p>
|
||
<p>首先,自然和其他的 I/O 设备一样,它有对应的<strong>接口和控制电路</strong>。现在的 SSD 硬盘用的是 SATA 或者 PCI Express 接口。在控制电路里,有一个很重要的模块,叫作<strong>FTL</strong>(Flash-Translation Layer),也就是<strong>闪存转换层</strong>。这个可以说是 SSD 硬盘的一个核心模块,SSD 硬盘性能的好坏,很大程度上也取决于 FTL 的算法好不好。现在容我卖个关子,我们晚一会儿仔细讲 FTL 的功能。</p>
|
||
<p>接下来是<strong>实际 I/O 设备</strong>,它其实和机械硬盘很像。现在新的大容量 SSD 硬盘都是 3D 封装的了,也就是说,是由很多个裸片(Die)叠在一起的,就好像我们的机械硬盘把很多个盘面(Platter)叠放再一起一样,这样可以在同样的空间下放下更多的容量。</p>
|
||
<p><img src="assets/0eee44535a925825b657bcac6afb72d3.jpeg" alt="img" /></p>
|
||
<p>接下来,一张裸片上可以放多个<strong>平面</strong>(Plane),一般一个平面上的存储容量大概在 GB 级别。一个平面上面,会划分成很多个块(Block),一般一个块(Block)的存储大小, 通常几百 KB 到几 MB 大小。一个块里面,还会区分很多个页(Page),就和我们内存里面的页一样,一个页的大小通常是 4KB。</p>
|
||
<p>在这一层一层的结构里面,处在最下面的两层块和页非常重要。</p>
|
||
<p>对于 SSD 硬盘来说,数据的<strong>写入</strong>叫作 Program。写入不能像机械硬盘一样,通过<strong>覆写</strong>(Overwrite)来进行的,而是要先去<strong>擦除</strong>(Erase),然后再写入。</p>
|
||
<p>SSD 的读取和写入的基本单位,不是一个比特(bit)或者一个字节(byte),而是一个<strong>页</strong>(Page)。SSD 的擦除单位就更夸张了,我们不仅不能按照比特或者字节来擦除,连按照<strong>页</strong>来擦除都不行,我们必须按照<strong>块</strong>来擦除。</p>
|
||
<p>而且,你必须记住的一点是,SSD 的使用寿命,其实是每一个块(Block)的擦除的次数。你可以把 SSD 硬盘的一个平面看成是一张白纸。我们在上面写入数据,就好像用铅笔在白纸上写字。如果想要把已经写过字的地方写入新的数据,我们先要用橡皮把已经写好的字擦掉。但是,如果频繁擦同一个地方,那这个地方就会破掉,之后就没有办法再写字了。</p>
|
||
<p>我们上面说的 SLC 的芯片,可以擦除的次数大概在 10 万次,MLC 就在 1 万次左右,而 TLC 和 QLC 就只在几千次了。这也是为什么,你去购买 SSD 硬盘,会看到同样的容量的价格差别很大,因为它们的芯片颗粒和寿命完全不一样。</p>
|
||
<h3>SSD 读写的生命周期</h3>
|
||
<p>下面我们来实际看一看,一块 SSD 硬盘在日常是怎么被用起来的。</p>
|
||
<p>我用三种颜色分别来表示 SSD 硬盘里面的页的不同状态,白色代表这个页从来没有写入过数据,绿色代表里面写入的是有效的数据,红色代表里面的数据,在我们的操作系统看来已经是删除的了。</p>
|
||
<p><img src="assets/966e51db8354922b533e1db236337e81.jpeg" alt="img" /></p>
|
||
<p>一开始,所有块的每一个页都是白色的。随着我们开始往里面写数据,里面的有些页就变成了绿色。</p>
|
||
<p>然后,因为我们删除了硬盘上的一些文件,所以有些页变成了红色。但是这些红色的页,并不能再次写入数据。因为 SSD 硬盘不能单独擦除一个页,必须一次性擦除整个块,所以新的数据,我们只能往后面的白色的页里面写。这些散落在各个绿色空间里面的红色空洞,就好像硬盘碎片。</p>
|
||
<p>如果有哪一个块的数据一次性全部被标红了,那我们就可以把整个块进行擦除。它就又会变成白色,可以重新一页一页往里面写数据。这种情况其实也会经常发生。毕竟一个块不大,也就在几百 KB 到几 MB。你删除一个几 MB 的文件,数据又是连续存储的,自然会导致整个块可以被擦除。</p>
|
||
<p>随着硬盘里面的数据越来越多,红色空洞占的地方也会越来越多。于是,你会发现,我们就要没有白色的空页去写入数据了。这个时候,我们要做一次类似于 Windows 里面“磁盘碎片整理”或者 Java 里面的“内存垃圾回收”工作。找一个红色空洞最多的块,把里面的绿色数据,挪到另一个块里面去,然后把整个块擦除,变成白色,可以重新写入数据。</p>
|
||
<p>不过,这个“磁盘碎片整理”或者“内存垃圾回收”的工作,我们不能太主动、太频繁地去做。因为 SSD 的擦除次数是有限的。如果动不动就搞个磁盘碎片整理,那么我们的 SSD 硬盘很快就会报废了。</p>
|
||
<p>说到这里,你可能要问了,这是不是说,我们的 SSD 硬盘的容量是用不满的?因为我们总会遇到一些红色空洞?</p>
|
||
<p><img src="assets/e7fcd994384145eefde614aaf3b45874.jpeg" alt="img" /></p>
|
||
<p>没错,一块 SSD 的硬盘容量,是没办法完全用满的。不过,为了不得罪消费者,生产 SSD 硬盘的厂商,其实是预留了一部分空间,专门用来做这个“磁盘碎片整理”工作的。一块标成 240G 的 SSD 硬盘,往往实际有 256G 的硬盘空间。SSD 硬盘通过我们的控制芯片电路,把多出来的硬盘空间,用来进行各种数据的闪转腾挪,让你能够写满那 240G 的空间。这个多出来的 16G 空间,叫作<strong>预留空间</strong>(Over Provisioning),一般 SSD 的硬盘的预留空间都在 7%-15% 左右。</p>
|
||
<h2>总结延伸</h2>
|
||
<p>到这里,相信你对 SSD 硬盘的写入和擦除的原理已经清楚了,也明白了 SSD 硬盘的使用寿命受限于可以擦除的次数。</p>
|
||
<p>仔细想一想,你会发现 SSD 硬盘,特别适合读多写少的应用。在日常应用里面,我们的系统盘适合用 SSD。但是,如果我们用 SSD 做专门的下载盘,一直下载各种影音数据,然后刻盘备份就不太好了,特别是现在 QLC 颗粒的 SSD,它只有几千次可擦写的寿命啊。</p>
|
||
<p>在数据中心里面,SSD 的应用场景也是适合读多写少的场景。我们拿 SSD 硬盘用来做数据库,存放电商网站的商品信息很合适。但是,用来作为 Hadoop 这样的 Map-Reduce 应用的数据盘就不行了。因为 Map-Reduce 任务会大量在任务中间向硬盘写入中间数据再删除掉,这样用不了多久,SSD 硬盘的寿命就会到了。</p>
|
||
<p>好了,最后让我们总结一下。</p>
|
||
<p>这一讲,我们从 SSD 的物理原理,也就是“电容 + 电压计”的组合,向你介绍了 SSD 硬盘存储数据的原理,以及从 SLC、MLC、TLC,直到今天的 QLC 颗粒是怎么回事儿。</p>
|
||
<p>然后,我们一起看了 SSD 硬盘的物理构造,也就是裸片、平面、块、页的层次结构。我们对于数据的写入,只能是一页一页的,不能对页进行覆写。对于数据的擦除,只能整块进行。所以,我们需要用一个,类似“磁盘碎片整理”或者“内存垃圾回收”这样的机制,来清理块当中的数据空洞。而 SSD 硬盘也会保留一定的预留空间,避免出现硬盘无法写满的情况。</p>
|
||
<p>到了这里,我们 SSD 硬盘在硬件层面的写入机制就介绍完了。不过,更有挑战的一个问题是,在这样的机制下,我们怎么尽可能延长 SSD 的使用寿命呢?如果要开发一个跑在 SSD 硬盘上的数据库,我们可以利用 SSD 的哪些特性呢?想要知道这些,请你一定要记得回来听下一讲。</p>
|
||
<h2>推荐阅读</h2>
|
||
<p>想要对于 SSD 的硬件实现原理有所了解,我推荐你去读一读这一篇<a href="https://www.anandtech.com/show/5067/understanding-tlc-nand">Understand TLC NAND</a>。</p>
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<div style="float: left">
|
||
<a href="/专栏/深入浅出计算机组成原理/45 机械硬盘:Google早期用过的“黑科技”.md.html">上一页</a>
|
||
</div>
|
||
<div style="float: right">
|
||
<a href="/专栏/深入浅出计算机组成原理/47 SSD硬盘(下):如何完成性能优化的KPI?.md.html">下一页</a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<a class="off-canvas-overlay" onclick="hide_canvas()"></a>
|
||
</div>
|
||
<script defer src="https://static.cloudflareinsights.com/beacon.min.js/v652eace1692a40cfa3763df669d7439c1639079717194" integrity="sha512-Gi7xpJR8tSkrpF7aordPZQlW2DLtzUlZcumS8dMQjwDHEnw9I7ZLyiOj/6tZStRBGtGgN6ceN6cMH8z7etPGlw==" data-cf-beacon='{"rayId":"70997aed1eda3cfa","version":"2021.12.0","r":1,"token":"1f5d475227ce4f0089a7cff1ab17c0f5","si":100}' crossorigin="anonymous"></script>
|
||
</body>
|
||
<!-- Global site tag (gtag.js) - Google Analytics -->
|
||
<script async src="https://www.googletagmanager.com/gtag/js?id=G-NPSEEVD756"></script>
|
||
<script>
|
||
window.dataLayer = window.dataLayer || [];
|
||
function gtag() {
|
||
dataLayer.push(arguments);
|
||
}
|
||
gtag('js', new Date());
|
||
gtag('config', 'G-NPSEEVD756');
|
||
var path = window.location.pathname
|
||
var cookie = getCookie("lastPath");
|
||
console.log(path)
|
||
if (path.replace("/", "") === "") {
|
||
if (cookie.replace("/", "") !== "") {
|
||
console.log(cookie)
|
||
document.getElementById("tip").innerHTML = "<a href='" + cookie + "'>跳转到上次进度</a>"
|
||
}
|
||
} else {
|
||
setCookie("lastPath", path)
|
||
}
|
||
function setCookie(cname, cvalue) {
|
||
var d = new Date();
|
||
d.setTime(d.getTime() + (180 * 24 * 60 * 60 * 1000));
|
||
var expires = "expires=" + d.toGMTString();
|
||
document.cookie = cname + "=" + cvalue + "; " + expires + ";path = /";
|
||
}
|
||
function getCookie(cname) {
|
||
var name = cname + "=";
|
||
var ca = document.cookie.split(';');
|
||
for (var i = 0; i < ca.length; i++) {
|
||
var c = ca[i].trim();
|
||
if (c.indexOf(name) === 0) return c.substring(name.length, c.length);
|
||
}
|
||
return "";
|
||
}
|
||
</script>
|
||
</html>
|