liwen01 2024.07.07

前言

yaffs 是专为nand flash 设计的一款文件系统,与jffs 类似,都是属于日志结构文件系统。与jffs 不同的是,yaffs 文件系统利用了nand flash 一些特有属性,所以在数据读写擦除和回收上都有较大的差异。

关于jffs2文件系统的介绍可以查看《文件系统(八):Linux JFFS2文件系统工作原理、优势与局限

这里先介绍一下nand flash的一些基础知识,有助于后面理解yaffs的设计原理。

(一)flash 基础

flash分为nor flashnand flash两类:

nor flash: 成本较高,容量较小,优点是读写数据不容易出错,比较适用于存储关键数据,比如程序固件、配置参数等。

nand flash :成本较低,相对便宜,容量较大,但是数据比较容易出错,所以一般都需要有对应的软件或者硬件的校验算法(ECC),比较适合用来储存大容量且数据安全要求不是非常严格的数据,比如照片、视频等。

(1)nand flash 数据存储单元

nand flash数据存储单元从概念上来说,由大到小有:

Nand Flash(Package) -> Chip(Die) -> Plane -> Block -> Page(Chunk) -> OOB(Spare data)

其中有些存储单元,在一些不同的资料上它们的叫法不太一样,比如page(页),、有些资料上介绍的是Chunk,在有些软件编程中,也有可能被介绍为扇区sector

Nand Flash:也叫Package,这是我们在PCBA上看到的已经封装好的整科芯片,带有封装有IO引脚,可以直接焊接到PCB上使用。

Chip:也叫Die(裸片),这是独立的硅片,包含存储单元和控制电路,一个Package 中可以包含多个Die。

Plane : Plane是die内部的一个逻辑分区。每个die通常被划分为多个plane,以实现并行操作。每个plane有独立的寄存器和数据缓存,因此可以同时进行多个操作(如读取、写入、擦除),从而提高性能。

Block :NAND Flash存储的基本单位。

Page :也叫chunk,NAND Flash中最小的可编程单元。

OOB(Out-Of-Band) :也叫Spare data,OOB区域是每个page中额外的存储空间,用于存储元数据,例如错误校正码(ECC)、坏块标记和其他管理信息.

(2)nand flash 特性

nand flash 有一些特殊的属性,也是因为这些特殊的属性才有了yaffs文件系统的特殊设计

  • 数据读写的最小单位是page(chunk)
  • 数据写入之前,写入位置需要是被擦除过了的
  • 数据擦除的最小单位是block
  • block里面的page,只能按顺序写入,不能任意page写入
  • oob的数据是随着page(chunk)的数据一同被写入
  • nand flash有编程干扰读取干扰配对页面等问题,会引起自身或是配对页面的位翻转。

(3)数据存储

结合nand flash的特性,从应用软件编程的角度来看,整个nand flash空间是由各page(chunk)组成,每个page(chunk)后面跟随一个与之对应的oob.

不同型号不同厂家生产的nand flash,它的block、page、oob等大小有可能不一样,在软件开发或是制作yaffs文件系统时,首先需要确认nand flash的参数。

(二)yaff2 数据格式

yaffs 有两个版本,yaffs1与yaffs2,主要区别是yaffs2可以支持比512Byte更大的chunk。它发布于2003年,比jffs2晚一两年被设计,但距今也二十多年了。

下面内容,yaffs 是代指yaffs1和yaffs2。关于yaffs文件系统的详细介绍,可以从官方网站下载到最新的代码和说明文档:https://www.aleph1.co.uk/gitweb/

(1)yaffs2 数据打包

  1. 创建4个测试目录,每个目录各创建一个测试文件,里面写有少量字符数据:
biao@ubuntu:~/test/yaffs/yaffs2_fs$ tree
.
├── test1
│   └── file1
├── test2
│   └── file2
├── test3
│   └── file3
└── test4
└── file4 4 directories, 4 files

在制作成yaffs2镜像文件之前,4个目录和文件的大小如下:

biao@ubuntu:~/test/yaffs$ du yaffs2_fs
8 yaffs2_fs/test3
8 yaffs2_fs/test2
8 yaffs2_fs/test1
8 yaffs2_fs/test4
36 yaffs2_fs
biao@ubuntu:~/test/yaffs$
  1. 下载最新yaffs源码,在yaffs2/utils 目录执行make,编译生成mkyaffs2image打包程序
  2. 使用默认参数对测试目录进行打包
biao@ubuntu:~/test/yaffs$ ./mkyaffs2image yaffs2_fs yaffs2_fs.img
mkyaffs2image: image building tool for YAFFS2 built Jul 7 2024
Processing directory yaffs2_fs into image file yaffs2_fs.img
Object 257, yaffs2_fs/test3 is a directory
Object 258, yaffs2_fs/test3/file3 is a file, 1 data chunks written
Object 259, yaffs2_fs/test2 is a directory
Object 260, yaffs2_fs/test2/file2 is a file, 1 data chunks written
Object 261, yaffs2_fs/test1 is a directory
Object 262, yaffs2_fs/test1/file1 is a file, 1 data chunks written
Object 263, yaffs2_fs/test4 is a directory
Object 264, yaffs2_fs/test4/file4 is a file, 1 data chunks written
Operation complete.
16 objects in 5 directories
12 NAND pages
biao@ubuntu:~/test/yaffs$

查看yaffs2_fs.img镜像文件信息:

biao@ubuntu:~/test/yaffs$ stat yaffs2_fs.img
File: yaffs2_fs.img
Size: 135168 Blocks: 264 IO Block: 4096 regular file
Device: 801h/2049d Inode: 7874075 Links: 1
Access: (0600/-rw-------) Uid: ( 1000/ biao) Gid: ( 1000/ biao)
Access: 2024-07-07 23:12:18.195919283 +0800
Modify: 2024-07-07 23:10:19.798582920 +0800
Change: 2024-07-07 23:10:19.798582920 +0800
Birth: -
biao@ubuntu:~/test/yaffs$

从yaffs2_fs.img镜像文件中我们看到,打包后的镜像文件比我们原来的目录文件要大很多,打包前是36KByte,打包后是132KByte,这是为什么呢?

(2)yaffs 数据分析

使用hexdunp命令直接查看yaffs2_fs.img镜像文件数据:

biao@ubuntu:~/test/yaffs$ hexdump -C yaffs2_fs.img
00000000 03 00 00 00 01 00 00 00 ff ff 74 65 73 74 33 00 |..........test3.|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
.........
.........
*
00000840 01 00 00 00 01 01 00 00 ff ff 66 69 6c 65 33 00 |..........file3.|
00000850 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00000940 00 00 00 00 00 00 00 00 00 00 ff ff b4 81 00 00 |................|
00000950 e8 03 00 00 e8 03 00 00 f4 45 85 66 7e e5 70 66 |.........E.f~.pf|
00000960 43 45 85 66 1d 00 00 00 ff ff ff ff ff ff ff ff |CE.f............|
00000970 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
*
.........
.........
*
00001080 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 |cccccccccccccccc|
00001090 63 63 63 63 63 63 63 63 63 63 63 63 0a ff ff ff |cccccccccccc....|
000010a0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
*
.........
.........

从hex数据中我们可以直观的看到文件名信息和文件里面的数据,也就是说文件名和文件里面的数据都是未压缩的。

我们对mkyaffsimage.c的源码进行分析,在默认参数下mkyaffsimage打包的镜像文件,它的chunk、spare、block大小信息如下:

#define chunkSize 2048
#define spareSize 64
#define pagesPerBlock 64

yaffs2的镜像文件是由object_header、data、yaffs_spare 三个部分组成,每个object_header、data 至少占用一个chunk,yaffs_spare 实际上也就是oob数据,是存储在spare空间。

(3)yaffs2 目录

我们对上面yaffs2_fs.img的镜像文件进行分析,先看最开始的数据,是test3目录obj

00000000  03 00 00 00 01 00 00 00  ff ff 74 65 73 74 33 00  |..........test3.|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00000100 00 00 00 00 00 00 00 00 00 00 ff ff fd 41 00 00 |.............A..|
00000110 e8 03 00 00 e8 03 00 00 f4 45 85 66 7e e5 70 66 |.........E.f~.pf|
00000120 43 45 85 66 ff ff ff ff ff ff ff ff ff ff ff ff |CE.f............|
00000130 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
*
000001c0 ff ff ff ff ff ff ff ff ff ff ff ff 00 00 00 00 |................|
000001d0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
*
00000800 00 10 00 00 01 01 00 00 00 00 00 00 ff ff 00 00 |................|
00000810 25 00 00 00 00 00 00 00 ff ff ff ff ff ff ff ff |%...............|
00000820 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
*

0~0x800 地址的数据是object_header数据结构,后面是oob的数据结构,详细解析数据如下:

从目录解析表格中我们可以看到如下信息:

  1. 未填写区域是数据0xFF,也就是未写入数据
  2. object_header大小为512Byte
  3. oob 大小为64Byte,与上面代码设置的相同
  4. 这里file_size_low为0xFF,表示不携带实际数据,实际也是没有data段
  5. obj_id 是从0x100(256)开始,在整个文件系统中,obj_id是不重复的,chunk更新的时候,obj_id保持不变

(3)yaffs2 文件

下面数据是file3的数据结构

00000840  01 00 00 00 01 01 00 00  ff ff 66 69 6c 65 33 00  |..........file3.|
00000850 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00000940 00 00 00 00 00 00 00 00 00 00 ff ff b4 81 00 00 |................|
00000950 e8 03 00 00 e8 03 00 00 f4 45 85 66 7e e5 70 66 |.........E.f~.pf|
00000960 43 45 85 66 1d 00 00 00 ff ff ff ff ff ff ff ff |CE.f............|
00000970 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
*
00000a00 ff ff ff ff ff ff ff ff ff ff ff ff 00 00 00 00 |................|
00000a10 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
*
00000a30 00 00 00 00 ff ff ff ff ff ff ff ff ff ff ff ff |................|
00000a40 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
*
00001040 00 10 00 00 02 01 00 00 00 00 00 00 ff ff 00 00 |................|
00001050 26 00 00 00 00 00 00 00 ff ff ff ff ff ff ff ff |&...............|
00001060 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
*
00001080 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 |cccccccccccccccc|
00001090 63 63 63 63 63 63 63 63 63 63 63 63 0a ff ff ff |cccccccccccc....|
000010a0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
*
00001880 00 10 00 00 02 01 00 00 01 00 00 00 1d 00 00 00 |................|
00001890 00 00 00 00 08 00 00 00 08 00 00 00 ff ff ff ff |................|
000018a0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
*

file3是一个文件,其中包括2个chunk:一个是Object,另外一个是data,其中每个chunk后面有一个与之对应的oob

与目录相比,文件有file_size_low,chunk_id,还有data chunk。我们看file3实际数据:

biao@ubuntu:~/test/yaffs$ stat yaffs2_fs/test3/file3
File: yaffs2_fs/test3/file3
Size: 29 Blocks: 8 IO Block: 4096 regular file
Device: 801h/2049d Inode: 7874095 Links: 1
Access: (0664/-rw-rw-r--) Uid: ( 1000/ biao) Gid: ( 1000/ biao)
Access: 2024-07-07 23:57:37.355671911 +0800
Modify: 2024-07-07 23:40:14.962499985 +0800
Change: 2024-07-07 23:34:11.067767029 +0800
Birth: -
biao@ubuntu:~/test/yaffs$ cat yaffs2_fs/test3/file3
cccccccccccccccccccccccccccc
biao@ubuntu:~/test/yaffs$

对比发现data chunk中存储的数据,就是file3文件里面的实际数据。

(三)工作原理

(1)yaffs2 挂载

上面我们分析了目录和文件obj的数据结构,实际yaffs还支持其它的文件类型:

enum yaffs_obj_type {
YAFFS_OBJECT_TYPE_UNKNOWN,
YAFFS_OBJECT_TYPE_FILE,
YAFFS_OBJECT_TYPE_SYMLINK,
YAFFS_OBJECT_TYPE_DIRECTORY,
YAFFS_OBJECT_TYPE_HARDLINK,
YAFFS_OBJECT_TYPE_SPECIAL
};

从obj 类型结构体中我们可以看到,还支持软连接、硬连接和特殊文件类型。它们与常规的文件、目录一样,都有object_header 结构,关键的元数据信息都是存储在oob中。

实际yaffs文件系统在挂载的时候,并不需要像jffs2一样扫描整个flash空间。在yaffs文件系统中,只需要先扫描oob里面的数据就可以构建出文件、目录与chunk之间的关系,再结合object_header信息就可以构建出整个文件系统的信息。所以yaffs2在同等大小的文件系统中,挂载速度是会比jffs2快的。

(2)yaffs2数据更新

回顾我们前面介绍的nand flash特性:

  • 数据读写的最小单位是page(chunk)
  • 数据写入之前,写入位置需要是被擦除过了的
  • 数据擦除的最小单位是block
  • block里面的page,只能按顺序写入,不能任意page写入
  • oob的数据是随着page的数据一同被写入

对于我们上面介绍的file3文件,如果我们要对它进行修改或是删除,在flash中是需要怎么操作的呢?

  1. 首先找到要修改的chunk,将数据读取到内存中,再对其数据进行修改,最后将修改后的数据写入到一个新的chunk
  2. 新的数据写入新chunk的同时,与它对应的oob数据也会被一同写入新chunk对应的oob区域

oob的数据是随着chunk的数据写入flash中的,但是nand flash 的擦除又是按block进行擦除,如果不擦除,数据又不能重新被写入,那要怎么标记file3 存储原来数据的chunk为无效呢?

在yaffs2中,它是通过oob中的obj id来标记是否同一个数据chunk,通过seq_number来标记哪个chunk的数据是最新的,如果不是最新的,那就是无效的了。

比如在文件系统中,有多个chunk它们有相同的obj id,说明这些chunk都是这个obj id 的不同修改版本的同一组数据,seq_number值最大的是最新的数据,其它的则都是无效数据。每一次修改,seq_number就会增加1。

这里是通过软件方法来标记数据无效,实际物理数据是没有做无效标记的,数据也没有被清除。物理上的标记无效和数据擦除,是需要等到垃圾回收的时候再对整个block进行擦除操作,这个时候标记的其实不是数据无效,而是chunk未使用.

在数据更新的操作中,核心的参数是obj id 和seq_number

(3)垃圾回收机制

从上面数据更新原理上我们知道,一个旧的数据,或是数据结构,在yaffs2文件系统中并不会标记它为无效,因为写入标志同样需要擦除再写入。在yaffs2文件系统中,是通过seq_number来标记数据版本的新旧,旧的则为无效数据。

在yaffs2的垃圾回收中,有两种方式:主动回收和被动回收:

主动回收:一个block中的绝大部分chunk数据都是无效的,文件系统会触发主动回收

被动回收:flash 已经没有干净的chunk可以继续使用,此时需要立即执行垃圾回收以释放空间。这里会把几个block中的有效数据合并到一块,腾出至少一个无效数据block以便进行整块擦除回收。

yaffs2文件系统中,为了平衡性能与回收功能,它的垃圾回收有两个特性:

  1. 尽可能地延迟进行垃圾回收
  2. 一次只处理一个块

(四)优缺点

(1)优点

  • 启动较快:与jffs2相比,它不需要全盘扫描flash空间,所以挂载所花费的时间相对较短。
  • 日志结构:采用日志结构的设计,在异常断电等情况下比较容易保持文件系统的一致性。
  • 磨损均衡:block内的chunk是按序写入,加上日志结构设备使yaffs自带磨损平衡。但是在垃圾回收的时候,并没有提供专门的算法,所以不是严格的磨损平衡,带有一些随机性。

(2)缺点

  • 无压缩功能:从上面我们对file3文件的分析可以看到,文件数据和元数据都未进行压缩,这个在对成本敏感的嵌入式设备中,是个劣势。
  • 元数据开销大: 每个obj都至少需要一个chunk存储object_header,元数据的开销大,浪费存储空间。
  • 扩展性差:不适合大容量的存储设备,管理大规模数据时性能可能下降。

(3)yaffs2与jffs2

yaffs2 文件系统与 jffs2 文件系统非常相似,都是基于裸flash设计的文件系统,jffs2 更常用于nor flash ,而yaffs2 是专为nand flash 而设计。它们都是日志结构文件系统,都有磨损平衡功能,但也都是随机磨损平衡。

它们都适合比较小容量的存储设备,因为jffs2挂载的时候需要全盘扫描flash查找元数据构建文件目录结构,所以jffs2在大容量存储设备中数据存储比较多时,挂载所需要的时间会比较长,耗用的内存也会比较多。

yaff2 是将关键元数据存储在oob中,nand flash的oob区域是固定的。挂载的时候只需要扫描oob区域数据就可以了,所以相比较jffs2,yaffs2的挂载启动速度会比较快一些。

jffs2的数据和元数据都是压缩的,并且支持多种压缩算法,这些yaffs2都没有,所以空间利用率yaffs2并没有jffs2高。

在产品功能没有明显优势的前提下,能把产品价格做低其实也是一个非常大的优势,所以nand flash的应用也越发的普及。但目前nand flash 使用比较多的是集成到FTL(Flash Translation Layer)设备中,比如TF卡,SD卡、SSD、U盘等。

jffs2和yaffs2文件系统,都是基于裸的flash来使用,它们并不适用于FTL设备,FTL设备使用比较多的文件系统是:FAT32,exFAT、NTFS、ext3、ext4等

关于存储介质和其它文件系统原理的介绍,可以查看前面文章:

文件系统(一):存储介质、原理与架构
文件系统(二):分区、格式化数据结构
文件系统(三):嵌入式、计算机系统启动流程与步骤
文件系统(四):FAT32文件系统实现原理
文件系统(五):exFAT 文件系统原理详解
文件系统(六):一文看懂linux ext4文件系统工作原理
文件系统(七):文件系统崩溃一致性、方法、原理与局限
文件系统(八):Linux JFFS2文件系统工作原理、优势与局限

结尾

yaffs2目前在嵌入式设备中使用率还是比较高,了解它的工作原理,有助于更好地使用它。另外从官方资料上看,yaffs 是需要授权收费的,如果有使用yaffs2文件系统的设备,需要考虑是否存在版权法律风险。

【如果你觉得文章内容对你有帮助,那就点个赞、关注一下吧】

------------------End------------------如需获取更多内容请关注 liwen01 公众号

文件系统(九):一文看懂yaffs2文件系统原理的更多相关文章

  1. 一文看懂Transformer内部原理(含PyTorch实现)

    Transformer注解及PyTorch实现 原文:http://nlp.seas.harvard.edu/2018/04/03/attention.html 作者:Alexander Rush 转 ...

  2. 一文看懂大数据的技术生态圈,Hadoop,hive,spark都有了

    一文看懂大数据的技术生态圈,Hadoop,hive,spark都有了 转载: 大数据本身是个很宽泛的概念,Hadoop生态圈(或者泛生态圈)基本上都是为了处理超过单机尺度的数据处理而诞生的.你可以把它 ...

  3. 【转帖】一文看懂docker容器技术架构及其中的各个模块

    一文看懂docker容器技术架构及其中的各个模块 原创 波波说运维 2019-09-29 00:01:00 https://www.toutiao.com/a6740234030798602763/ ...

  4. 一文看懂web服务器、应用服务器、web容器、反向代理服务器区别与联系

    我们知道,不同肤色的人外貌差别很大,而双胞胎的辨识很难.有意思的是Web服务器/Web容器/Web应用程序服务器/反向代理有点像四胞胎,在网络上经常一起出现.本文将带读者对这四个相似概念如何区分. 1 ...

  5. 一文看懂https如何保证数据传输的安全性的【转载、收藏】

    一文看懂https如何保证数据传输的安全性的   一文看懂https如何保证数据传输的安全性的 大家都知道,在客户端与服务器数据传输的过程中,http协议的传输是不安全的,也就是一般情况下http是明 ...

  6. [转帖]一文看懂web服务器、应用服务器、web容器、反向代理服务器区别与联系

    一文看懂web服务器.应用服务器.web容器.反向代理服务器区别与联系 https://www.cnblogs.com/vipyoumay/p/7455431.html 我们知道,不同肤色的人外貌差别 ...

  7. [转帖] 一文看懂:"边缘计算"究竟是什么?为何潜力无限?

    一文看懂:"边缘计算"究竟是什么?为何潜力无限? 转载cnbeta   云计算 雾计算 边缘计算...   知名创投调研机构CB Insights撰文详述了边缘计算的发展和应用前景 ...

  8. 一文看懂Stacking!(含Python代码)

    一文看懂Stacking!(含Python代码) https://mp.weixin.qq.com/s/faQNTGgBZdZyyZscdhjwUQ

  9. Nature 为引,一文看懂个体化肿瘤疫苗前世今生

    进入2017年,当红辣子鸡PD-1疗法,一路横扫多个适应症.而CAR-T治疗的“小车”在获得FDA专委会推荐后也已经走上高速路,成为免疫治疗又一里程碑事件.PD-1.CAR-T之后,下一个免疫治疗产品 ...

  10. 转载来自朱小厮博客的 一文看懂Kafka消息格式的演变

    转载来自朱小厮博客的 一文看懂Kafka消息格式的演变     ✎摘要 对于一个成熟的消息中间件而言,消息格式不仅关系到功能维度的扩展,还牵涉到性能维度的优化.随着Kafka的迅猛发展,其消息格式也在 ...

随机推荐

  1. 鸿蒙stage模型

    app.json5全局的配置文件 icon和label是应用列表的 module.json5模块配置文件 中有一个abilities其中的icon和label才是桌面的图标和名称 日志的话就是hail ...

  2. C++ placement new学习

    通常创建对象使用new操作,但这样无法指定在具体某一块内存开辟空间创建对象.而如果 可以指定开辟空间的内存位置,我们可以编写内存池高效的复用同一个内存位置,这样可以避免系统频繁申请可用内存 所占用的时 ...

  3. vue学习笔记之父组件子组件的传值

    一  在前端开发过程中,很多情况下一个页面无法装载大部分的代码,所以需要子组件来完成父组件的任务,下面我来展示一下,组件之间如何进行传值以及常见的坑,首先上代码 1.1   父组件代码 <tem ...

  4. linux各个目录详细说明

    在linux中一切皆文件,每个目录均有自己特定的作用,下面进行详细说明. 目录 说明 / 处于linux系统树形结构的最顶端,它是linux文件系统的入口,所有的目录.文件.设备都在 / 之下 /bi ...

  5. uni-app写微信小程序,data字段循环引用

    在写程序过程中,需要使用到 globalData里的内容,而这个全局变量,在uni-app上需要通过: var app=getApp(); app.globalData.xxx=xxx来使用. 我觉得 ...

  6. mySql脚本转换成sqlserver脚本(主流数据库的脚本都能转换,需要使用powerdesigner)

    我使用的powerdesginer版本是16.5,只需要脚本文件就可以了,不需要安装mysql和sqlserver. 文件->反向工程->Database... 选择原脚本文件的数据库类型 ...

  7. group_concat 和 case when 的坑

    SELECT size,instrument_id, (CASE side WHEN "sell" THEN group_concat(id ORDER BY id) END )a ...

  8. SpringBoot使用@Value获取不到值的问题

    背景 在一次SpringBoot项目改造为Cloud的过程中,使用Nacos作为配置中心获取属性,改造后程序启动报错,查看日志,定位到代码: 解决方案 如果了解Bean的生命周期的同学应该知道,Spr ...

  9. python 如何判断一组数呈上升还是下降趋势

    1. python 判断一组数呈上升还是下降趋势的方法 要判断一组数(数列)是呈上升趋势.下降趋势还是无明显趋势,我们可以比较数列中相邻元素的差值.如果大部分差值都是正数,则数列呈上升趋势:如果大部分 ...

  10. 使用 INFINI Console 实现 Elasticsearch 的增量数据迁移

    功能介绍 # 在 INFINI Console 1.3.0 版本里,数据迁移功能增加了对增量迁移的支持.这篇文章将会介绍增量迁移的具体使用方法和实现原理. 场景介绍 # 以常见的日志场景为例,假设 A ...