<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>存储 on 涯余的博客</title><link>https://hangyan.github.io/tags/%E5%AD%98%E5%82%A8/</link><description>Recent content in 存储 on 涯余的博客</description><generator>Hugo</generator><language>zh</language><managingEditor>hang.yan@hotmail.com (涯余)</managingEditor><webMaster>hang.yan@hotmail.com (涯余)</webMaster><lastBuildDate>Sat, 20 Apr 2019 22:35:17 +0800</lastBuildDate><atom:link href="https://hangyan.github.io/tags/%E5%AD%98%E5%82%A8/index.xml" rel="self" type="application/rss+xml"/><item><title>JFFS3 文件系统</title><link>https://hangyan.github.io/post/2019-04-20-jffs3/</link><pubDate>Sat, 20 Apr 2019 22:35:17 +0800</pubDate><author>hang.yan@hotmail.com (涯余)</author><guid>https://hangyan.github.io/post/2019-04-20-jffs3/</guid><description>&lt;!-- toc --&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://hangyan.github.io/post/2019-04-20-jffs3/#%e9%97%aa%e5%ad%98%e5%af%b9%e6%96%87%e4%bb%b6%e7%b3%bb%e7%bb%9f%e7%9a%84%e5%bd%b1%e5%93%8d"&gt;闪存对文件系统的影响&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://hangyan.github.io/post/2019-04-20-jffs3/#%e9%97%aa%e5%ad%98%e8%bd%ac%e6%8d%a2%e5%b1%82"&gt;闪存转换层&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hangyan.github.io/post/2019-04-20-jffs3/#jffs3"&gt;JFFS3&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://hangyan.github.io/post/2019-04-20-jffs3/#jffs2-%e7%9a%84%e9%97%ae%e9%a2%98"&gt;JFFS2 的问题&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hangyan.github.io/post/2019-04-20-jffs3/#index-%e7%9a%84%e5%ad%98%e5%82%a8"&gt;Index 的存储&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hangyan.github.io/post/2019-04-20-jffs3/#the-journal"&gt;The Journal&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hangyan.github.io/post/2019-04-20-jffs3/#garbage-collection"&gt;Garbage collection&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hangyan.github.io/post/2019-04-20-jffs3/#superblock"&gt;Superblock&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hangyan.github.io/post/2019-04-20-jffs3/#links"&gt;Links&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;!-- tocstop --&gt;
&lt;p&gt;看完了&lt;a href="https://hangyan.github.io/post/2019-04-18-flash/"&gt;闪存&lt;/a&gt;,继续看文件系统。网上搜了一圈，发现都是讲 Andriod 的目录结构的，讲文件系统本身的少。目前能确认的是历史上曾经用过 ext4,yaffs,yaffs2 等。
估计目前主流的应该是 ext4。不过在搜索的时候先发现了一篇讲 jffs3 的，它在嵌入式系统上应用比较广泛，也是针对 Flash 存储特定设计的文件系统。不太确定现在的使用范围，但是拿出来研究下还是不错的。&lt;/p&gt;
&lt;h2 id="闪存对文件系统的影响"&gt;闪存对文件系统的影响&lt;/h2&gt;
&lt;p&gt;闪存跟磁盘有很多不同的地方，在设计文件系统的时候，二者有很多不同的考量。简单的对比表格如下&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style="text-align: center"&gt;&lt;/th&gt;
&lt;th style="text-align: center"&gt;闪存&lt;/th&gt;
&lt;th style="text-align: center"&gt;磁盘&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;最小寻址单位(读)&lt;/td&gt;
&lt;td style="text-align: center"&gt;字节&lt;/td&gt;
&lt;td style="text-align: center"&gt;扇区&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;最小寻址单位(写)&lt;/td&gt;
&lt;td style="text-align: center"&gt;NOR FLASH 是字节，NAND FLASH 是页，擦除是块&lt;/td&gt;
&lt;td style="text-align: center"&gt;扇区&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;寿命&lt;/td&gt;
&lt;td style="text-align: center"&gt;由擦写块的最大可擦写次数&lt;/td&gt;
&lt;td style="text-align: center"&gt;机械故障&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;闪存的这些特性，导致我们在设计文件系统的时候，必须考虑以下的问题：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;out of place update&lt;/code&gt;: 对于磁盘来讲，我们更新数据可以直接原地更新。但是闪存不行，因为无法将 bit 位从 0 -&amp;gt; 1。所以对于闪存的数据更新只能是在另外一个地方写入数据，然后将原数据标记为 dirty,再通过 GC 来定期回收.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;wear leveling&lt;/code&gt;: 磨损平衡。闪存的使用寿命是由擦写块的最大可擦写次数来决定的。超过了最大可擦写次数，这个擦写块就成为坏块(bad block)了。因此为了避免某个擦写块被过度擦写，以至于它先于其他的擦写块达到最大可擦写次数，我们应该在尽量小的影响性能的前提下，使擦写操作均匀的分布在每个擦写块上&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="闪存转换层"&gt;闪存转换层&lt;/h3&gt;
&lt;p&gt;为了能让普通的文件系统(磁盘上的)能够在闪存上正常运行，需要有一个转换层：Flash Translation Layer（FTL）。它的功能就是将底层的闪存模拟成一个具有 512 字节扇区大小的标准块设备(block device)。对于文件系统来说，就像工作在一个普通的块设备上一样，没有任何的差别。&lt;/p&gt;</description></item><item><title>闪存</title><link>https://hangyan.github.io/post/2019-04-18-flash/</link><pubDate>Thu, 18 Apr 2019 21:01:13 +0800</pubDate><author>hang.yan@hotmail.com (涯余)</author><guid>https://hangyan.github.io/post/2019-04-18-flash/</guid><description>&lt;!-- toc --&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://hangyan.github.io/post/2019-04-18-flash/#%e5%9f%ba%e6%9c%ac%e5%ae%9a%e4%b9%89"&gt;基本定义&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hangyan.github.io/post/2019-04-18-flash/#nor--nand"&gt;NOR / NAND&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hangyan.github.io/post/2019-04-18-flash/#%e5%86%99%e6%93%a6%e9%99%a4"&gt;写/擦除&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hangyan.github.io/post/2019-04-18-flash/#emmc--ufs"&gt;eMMC / UFS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hangyan.github.io/post/2019-04-18-flash/#links"&gt;Links&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;!-- tocstop --&gt;
&lt;p&gt;本来看华为新弄了 FS 和编译器，想学习下。但是目前似乎放出来的技术资料并不多，就先做下技术储备。先研究下他们做这个优化的历史背景。一路看下来发现链路太长，EXT4、更早的文件系统、最后到了闪存。
大学课堂上学过，但到现在真要考我，估计也说不出个所以然，所以先记录下闪存相关的笔记。&lt;/p&gt;
&lt;h2 id="基本定义"&gt;基本定义&lt;/h2&gt;
&lt;p&gt;ROM 的一种，虽然看着是&lt;code&gt;read only&lt;/code&gt;，但是闪存属于的细分类别已经可以允许重写数据(EEPROM)。比较接近的两种细分类别对比来看：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;EPROM: 需要用紫外线照射才能重写数据(注定要被淘汰的技术)&lt;/li&gt;
&lt;li&gt;EEPROM: 多的一个&lt;code&gt;E&lt;/code&gt;便是&lt;code&gt;Electrically&lt;/code&gt;，可以用电擦除数据&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;自然 EEPROM 的应用更加广泛。目前手机上的存储主要就是闪存（EEPROM)。闪存用于手机等移动设备的一些原因如下:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;动态抗震性好(没有机械部件)&lt;/li&gt;
&lt;li&gt;极端环境下也比较可靠(手机三防)&lt;/li&gt;
&lt;li&gt;在擦除数据时比一般的 EEPROM 效率更高(区块对字节)&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="nor--nand"&gt;NOR / NAND&lt;/h2&gt;
&lt;p&gt;两种 flash 的类型，直接上一个比较简单的表格对比：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style="text-align: center"&gt;&lt;/th&gt;
&lt;th style="text-align: center"&gt;NOR&lt;/th&gt;
&lt;th style="text-align: center"&gt;NAND&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;抹写速度&lt;/td&gt;
&lt;td style="text-align: center"&gt;慢&lt;/td&gt;
&lt;td style="text-align: center"&gt;快&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;抹写次数&lt;/td&gt;
&lt;td style="text-align: center"&gt;低&lt;/td&gt;
&lt;td style="text-align: center"&gt;高 (10x)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;存取方式&lt;/td&gt;
&lt;td style="text-align: center"&gt;随机&lt;/td&gt;
&lt;td style="text-align: center"&gt;区块&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;成本&lt;/td&gt;
&lt;td style="text-align: center"&gt;高&lt;/td&gt;
&lt;td style="text-align: center"&gt;低&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;面积&lt;/td&gt;
&lt;td style="text-align: center"&gt;大&lt;/td&gt;
&lt;td style="text-align: center"&gt;小&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;适用场景&lt;/td&gt;
&lt;td style="text-align: center"&gt;微处理器&lt;/td&gt;
&lt;td style="text-align: center"&gt;普通存储&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;实际使用&lt;/td&gt;
&lt;td style="text-align: center"&gt;BIOS/机顶盒&lt;/td&gt;
&lt;td style="text-align: center"&gt;U 盘/SSD&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="写擦除"&gt;写/擦除&lt;/h2&gt;
&lt;p&gt;这也是一个容易忽略但是细究起来很容易让人迷惑的东西。为什么闪存有擦除的概念?
简单来讲，由于闪存特殊的物理构造，可以理解为&lt;code&gt;写&lt;/code&gt;操作只能写入&lt;code&gt;0&lt;/code&gt;,擦除操作相当于写入&lt;code&gt;1&lt;/code&gt;。&lt;a href="https://zhuanlan.zhihu.com/p/35115499"&gt;手机闪存和固态硬盘为什么擦除多了会损坏？&lt;/a&gt;这篇文章提供了具体的电路图示意：&lt;/p&gt;</description></item><item><title>Shard</title><link>https://hangyan.github.io/post/2017-08-11-sharding/</link><pubDate>Fri, 11 Aug 2017 21:37:39 +0800</pubDate><author>hang.yan@hotmail.com (涯余)</author><guid>https://hangyan.github.io/post/2017-08-11-sharding/</guid><description>&lt;!-- toc --&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://hangyan.github.io/post/2017-08-11-sharding/#%e4%bb%8b%e7%bb%8d"&gt;介绍&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://hangyan.github.io/post/2017-08-11-sharding/#%e5%88%86%e7%89%87%e7%ad%96%e7%95%a5"&gt;分片策略&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://hangyan.github.io/post/2017-08-11-sharding/#the-lookup-strategy"&gt;The Lookup strategy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hangyan.github.io/post/2017-08-11-sharding/#the-range-strategy"&gt;The Range strategy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hangyan.github.io/post/2017-08-11-sharding/#the-hash-strategy"&gt;The Hash strategy&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hangyan.github.io/post/2017-08-11-sharding/#%e7%9b%b8%e5%85%b3%e6%8a%80%e6%9c%af"&gt;相关技术&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://hangyan.github.io/post/2017-08-11-sharding/#brin"&gt;BRIN&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;!-- tocstop --&gt;
&lt;h1 id="介绍"&gt;介绍&lt;/h1&gt;
&lt;p&gt;Shard 指对数据的水平切分,每一个切分的部分都可以叫做一个&lt;code&gt;shard&lt;/code&gt;,它们拥有相同的 schema,但却拥有不同的数据集。对数据库来说，是指对数据库的表按行进行切分(与按列的垂直切分对应)，不同的 shard 可能位于不同的数据库服务器或者物理机器上。它的优势体现在以下几点:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;表的大小减少,索引体积减小,提升查询性能(某些方面)&lt;/li&gt;
&lt;li&gt;如果数据本身有比较明显的分区(比如国家,地区等),那么做 shard 很容易并且查询很大程度上都能落在一个 shard 上。&lt;/li&gt;
&lt;li&gt;水平扩展性好，可以通过添加新节点来扩充&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;劣势有以下几点:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;查询需要跨多个 shard 时会增加 latency&lt;/li&gt;
&lt;li&gt;因为 shard 经常只能做到某一位维度。所以在这一维度的查询的性能可能提高，但其他维度的查询的性能则可能会下降。&lt;/li&gt;
&lt;li&gt;跨 shard 的数据一致性和可用性也更加复杂和难以保障&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;shard 本身的问题让他成为一个&lt;code&gt;迫不得已&lt;/code&gt;的选择。尽量在没有其他优化方式的情况下选择 shard.理想情况下，应该有底层框架来处理 shard 而让应用层做到对 shard 无感知，不然还不如不用。&lt;/p&gt;
&lt;h2 id="分片策略"&gt;分片策略&lt;/h2&gt;
&lt;p&gt;如果将数据集进行 shard,有很多策略可以选择，常见的有&lt;/p&gt;
&lt;h3 id="the-lookup-strategy"&gt;The Lookup strategy&lt;/h3&gt;
&lt;p&gt;用 shard key 做一个映射表，包含不同 shard key 的请求会转发到相应的 shard 上。这种情况下，不同 shard key 的数据可能会落在同一个 shard 上，但相同 shard key 的数据则一定在同一个 shard 上.shard 与物理地址的映射也不能是一对一的，可以用类似于 consistent hashing 里面的那种 virtual node 的方式，设置一些&lt;code&gt;virtual shard&lt;/code&gt;，几个 virtual shard 可以对应于同样的物理位置(reblancing 的时候对上层代码的影响很小)。&lt;/p&gt;</description></item></channel></rss>