一, HDFS概述

1.1 HDFS的产生背景和定义

  1. 随着数据量越来越大,我们需要把文件分布存储到多台计算机上,分布式文件管理系统作为一种管理多台机器上文件的系统应运而生, HDFS是其中的一种.
  2. HDFS定义:
    • Hadoop Distributed File System,
    • 通过目录树来定位文件
    • 分布式的. 很多服务器联合起来实现功能,集群中的服务器有各自的角色.
    • 使用场景: 适合一次写入,多次读取的场景. 一个文件经过创建,写入和关闭后就不需要改变

1.2, HDFS的优缺点:

  • 优点:
  • 高容错性(多个副本, 自动恢复). 数据自动保存多个副本,通过增加副本的形式,提高容错性. 某一个副本丢失,它可以自动恢复.
  • 适合处理大数据(超大文件). GB,TB甚至于PB级别的数据或者是百万规模以上的文件数量.
  • 可构建在廉价机器上. 通过多副本机制,提高可靠性.
  • 缺点:
  • 不适合低延时数据访问. 比如毫秒级的存储数据,是做不到的, HDFS是为高数据吞吐量应用优化的, 这可能会以提高时间延迟为代价, 目前来说, 对于低延迟的访问需求, HBase是更好的选择.
  • 无法高效的对大量小文件进行存储.
    1. 存储大量小文件的话,它会占用NameNode大量的内存来存储文件系统的元数据. 由于NameNode的内存总是有限的,所以不可取.
    2. 小文件存储的寻址时间会超过读取时间,他违反了HDFS的设计目标.
  • 不支持并发(多个用户)写入,也不支持在文件的任意位置进行修改
    1. 一个文件只允许一个用户写,不允许多个用户同时写
    2. 仅支持数据追加(append)到文件末尾, 不支持文件的随机修改.

1.3, HDFS组成架构

  1. NameNode(nn),即master,他是一个管理者.
  • NameNode 执行的操作 主要分为三类, 如下表所示:
类别 说明
1. 维护管理HDFS的命名空间 维护整个文件系统的目录树, 文件/目录的元数据信息和文件的数据块索引(每个文件对应的数据块列表). 这些信息在NameNode中保存在两个文件中, 分别是 FSImame(文件系统镜像)和 Edits(编辑日志)
2. 确定数据块-DataNode的映射关系 client读取数据先访问NameNode, 由NN获取数据所在的DN, 然后client读取目标DN得到数据. 注意: 数据块-DataNode的映射关系是由NameNode根据DataNode上报的文件块信息动态重建的而不是持久化保存,从而减轻了NameNode的负担
3. 管理DataNode结点的状态报告 包括DataNode的健康状态报道和其所在结点上数据块的状态报告, 以便能够及时处理失效的DataNode

注意:

  1. FSImage-文件系统镜像, 在NameNode启动时对整个文件系统的快照;
  2. edits-编辑日志, 在NameNode启动之后, 记录对文件系统的改动序列;
  1. DataNode,即Slave,NameNode下达命令.DataNode执行实际的操作, 如下表所示:
类别 说明
1. 负责实际执行自身结点上数据的读写和存储 一般是文件系统客户端需要请求对NN指定的DataNode结点进行读写操作, DataNode作为数据结点的服务进程与文件系统打交道.
2. 定期向NameNode报告状态 每个DataNode会周期性地向NameNode发送心跳信号和文件块报告(心跳是每3秒一次,心跳返回结果带有namenode给该datanode的命令如复制块数据到另一台机器,或删除某个数据块。如果超过10分钟没有收到某个datanode的心跳,则认为该节点不可用)
3. 执行数据的流水线复制 当文件系统客户端从NameNode服务器进程获取到要进行复制的数据块列表后, 由DataNode完成文件块和块副本的流水线复制
  1. Client,客户端

    • 文件切分.文件上传HDFS的时候,Client将文件切分为一个个的Block,然后进行上传;
    • 与NameNode交互,获取文件的位置信息;
    • 与DataNode交互,读取或写入数据;
    • Client提供一些命令来管理HDFS,比如NameNode格式化;
    • Client可以通过一些命令来访问HDFS,比如对HDFS增删改查操作.
  2. Secondary NameNode: 并非NameNode的热备份,当NameNode挂掉后,并不会马上替换NameNode并提供服务

    • 辅助NameNode,分担其工作量,比如定期合并Fsimage和Edits,并推送给Namenode(保持一个较新的文件系统快照);
    • 在紧急情况下,可辅助恢复NameNode.

    对2NN的详细说明

1.4 HDFS文件块大小(面试重点)

HDFS中的文件在物理上是分块存储的(Block),块的大小可以通过配置参数(hdfs-default.xml文件中的dfs.blocksize)来规定, 默认大小在Hadoop2.x/3.x版本中是128M, 1.x版本中是64M.

Q: 为什么块的大小不能设置太小,也不能设置太大?

  1. HDFS块的大小设置主要取决于磁盘传输速率;
  2. HDFS的块设置太小,会增加寻址时间,程序一直在找块的开始位置;
  3. 如果块设置的太大,从磁盘传输数据的时间会明显大于定位这个块开始位置所需的时间. 导致程序在处理这块数据时, 会非常.
  • 总结: HDFS的块大小主要取决于磁盘传输速率。

二, HDFS的Shell操作

2.1 HDFS的常用命令

  • 格式:
    hadoop fs 具体命令 OR hdfs dfs 具体命令

2.2, 上传文件

  1. 先在HDFS创建一个测试文件夹

hdfs dfs -mkdir shellTest
注意: 不要忘记带路径符号正斜杠, ‘/’

  1. 本地剪切文件到HDFS

-moveFromLocal ./文件名 /目标目录 (命令大小写严格区分噢, movefromlocal就不对)

示例:

进入HDFS web管理页面(bigdata01:9870), 点击可以查看目录和文件

  1. 本地上传文件到HDFS

-put ./文件名 /目标目录
或者是, -copyFromLocal ./文件名 /目标目录名


  1. 追加文件到另一个已经存在文件的末尾

-appendToFile ./文件名 /目录名/文件名

举个栗子:

在本地新建一个cal.txt, 然后把cal指令(显示本月日历)结果追加到cal.txt(其实追加命令自己可以新建文件哈), 之后在hdfs中-touch新建一个time.txt, cal.txt追加到hdfs的/shellTest/time.txt中, 并-cat打印输出结果.

2.3, 下载文件

  1. 从HDFS下载文件到本地

-get /目录/文件 ./
或者是, -copyToLocal /目录名/文件名

示例:

  • 如果你下载文件同时并改个名,

2.4, 常用Shell命令

  1. -ls 查指定路径文件和目录的详细信息

    注意: HDFS的 -ls 操作等用于于的是 linux 的 ll操作

  2. -cat 打印输出文件内容

  3. -chmod(-chgrp -chown) 修改文件所属权限

  4. -mkdir 创建目录

  5. -cp, -mv 复制,移动文件;从HDFS的一个路径到另一个路径

  6. -rm 删除文件或目录(-rm -r)

  7. -tail 显示一个文件的末尾的1kb的数据

Q: 为什么要查看末尾? 因为末尾的文件内容随着追加操作不断更新,时效性较强.比如.日志文件.

  1. -du 统计文件夹的大小信息 ( -du -s 汇总加和, -h 以人类易读的方式显示)

第一列是文件的大小,第二列除以第一列的值是文件的副本数量;

如shuguo.txt这个文件大小是7B, 有14/7=2个副本;

-du -h -s 是文件夹的所有文件的信息
-du -h 是文件夹的总体信息

  1. -setrep (replication)设置HDFS中文件的副本数量

  • 实际还是只有三个副本, 因为目前只有这三台DataNode节点

这里设置的副本数只是记录在NameNode 的元数据中,是否真的会有这么多副本,还得看DataNode的数量。因为目前只有3台设备,最多也就3个副本,只有节点数的增加到8台时,副本数才能达到8。
!!! 一台机器一个副本,多了没意义!

三, 基于JAVA的HDFS的API操作

参见此文: 二-0, 大数据基础架构Haoop- 在Windows客户机上对HDFS的API操作

四, HDFS的读写流程(面试重点)

4.1, HDFS写数据流程

4.1.1 HDFS文件写入剖析(需要进一步深入)

具体步骤:

  1. 客户端通过 DistributedFileSystem模块向NameNode请求上传文件,NameNode检查目录结构(检查目标文件是否存在,父目录是否存在,权限是否满足);
  2. NameNode返回请求是否可以上传;
  3. 客户端对待传文件进行切分,分为若干个block (每个block的大小为64M 或者 128M),然后向NameNode请求上传第一个Block到哪几个DataNode服务器上;
  4. NameNode考虑每一个节点是否可用, 节点距离最近, 负载均衡等因素返回3个DataNode节点,分别为dn1,dn2,dn3;
  5. 客户端通过FSDataOutputStream模块请求dn1上传数据,dn1收到请求后会继续调用dn2,然后dn2调用dn3,将这个通信管道建立完成;
  6. dn1,dn2,dn3逐级应答客户端;
  7. 客户端开始往dn1上传第一个Block(先从磁盘读取数据放到一个本地内存缓存),以Packet为单位(大小为64k, 由多个chunk512字节+chunkSum4字节组成),dn1收到一个Packet就会传给dn2,dn2传给dn3; dn1每传一个packet会放入一个应答队列等待应答();
  8. 当一个Block传输完成之后,客户端再次请求NameNode上传第二个BLock的的服务器(重复执行3-7步).

待参考的文章
待参考文章2

4.1.2 网络拓扑-节点距离计算

在HDFS写数据的过程中,NameNode会选择离上传数据最近距离的DataNode接收数据,那么这个最近距离是如何计算的呢?
节点距离: 两个节点到达最近的共同祖先的距离总和( 什么是共同祖先, 比如一个机架中两个结点的共同祖先就是这个机架; ab两个机架中的两个节点的共同祖先就是ab两个机架构成的集群)

示例:

4.1.3 机架感知(副本存储节点选择)

选择策略(假如集群有三个副本)

  1. 第一个副本在Client所处的节点上,如果客户端在集群外,随机选一个;(节点越近,上传速率越快)
  2. 第二个副本在另一个机架的随机一个节点上;(保证数据的可靠性)
  3. 第三个副本在第二个副本所在机架的随机节点;(同时兼顾效率)

三个副本的机架感知概括如下: 跟Client同机架的其他一个节点, 别的机架A上的一个节点, 别的机架A上一个随机节点.

4.2, HDFS 读数据流程

具体步骤:

  1. 客户端通过 DistributedFileSystem 向 Namenode请求下载文件, NameNode通过查询元数据,找到文件块所在的DataNode地址;
  2. 挑选一台DataNode(节点最近,负载均衡 )服务器,请求读取数据;
  3. DataNode开始传输数据给客户端(从磁盘里面读取数据输入流,以Packet为单位来做校验);
  4. 客户端以Packet为 单位接收,先在本地缓存,然后写入目标文件;

五, NameNode和Secondary NameNode

5.1, NN和2NN工作机制-引言

首先思考一个问题: NameNode中的元数据是存储在哪里的?

  1. 如果把元数据存放在NameNode节点的磁盘中,因为经常需要进行随机访问,还有响应客户请求,所以必然会效率过低; 因此我们要把元数据存放到内存中.
  2. 但是,如果元数据只存在内存中,一旦断电,元数据丢失,整个集群就完犊子了, 所以我们引出了在磁盘中备份元数据,叫FsImage;
  3. 然而新问题又来了,当在内存中的元数据更新时,如果同时去更新FsImage,又会导致效率过低, 但是不更新的话又会发生一致性问题, 一旦NameNode断电,数据又丢了个鸡儿的.因此我们引入了 Edits文件(只进行追加操作,效率很高),每当元数据有更新或者添加元数据时,修改内存中的元数据并追加到Edits中.这样, 一旦NameNode节点断电,可以通过FsImage和Edits的合并,合并出当时的元数据.
  4. 但是! 如果长时间添加数据到Edits中而不及时合并,会导致该文件数据过大,效率降低,而且一旦断电,恢复元数据需要的时间过长.因此, 需要定期进行FsImage和Edits的合并, 如果这个操作由NameNode节点完成,又会导致效率过低,所以,我们又引入了一个新的节点Secondary NameNode, 专门用于FsImage和Edits的合并.

Fsimage 在磁盘中备份元数据;
Edits 记录对数据发生的修改;
Secondary NameNode定时合并上面两个文件;

参见此文: Secondary NameNode:它究竟有什么作用?

5.2, NN和2NN工作机制-详述

  1. 第一阶段: NameNode启动

    1. 第一次启动NameNode格式化后,创建Fsimage和Edits文件.如果不是第一次启动,则直接加载编辑日志和镜像文件到内存;
    2. 客户端对元数据进行增删改的请求;
    3. NameNode记录操作日志,更新滚动日志(记录到edits_inprogress);
    4. NameNode在内存中对元数据进行增删改;
  2. 第二阶段: Secondary NameNode工作

    1. Secondary NameNode询问NameNode是否需要CheckPoint. 直接带回NameNode是否检查结果;
    2. Secondary NameNode 执行CheckPoint;
    3. NameNode 滚动正在写的Edits日志;
    4. 滚动前的编辑日志(Edits)和镜像文件(fsimage)拷贝到 Secondary NameNode;
    5. Secondary NameNode加载编辑日志和镜像文件到内存,并进行合并;
    6. 生成新的镜像文件 fsimage.chkpoint;
    7. 拷贝fsimage.chkpoint回到NameNode;
    8. NameNode将fsimage.chkpoint重新命名为 fsimage,覆盖原来的fsimage.

checkpoint的触发条件:

  1. 定时时间到
  2. Edit中的数据满了

5.3, Fsimage和Edits文件的解析

NameNode 被格式化以后,将在/hadoop安装目录/data/tmp/dfs/name/current 目录下产生如下文件:

  1. fsimage文件: HDFS文件系统元数据的一个永久的检查点,其中包含HDFS文件系统的所有目录和inode的序列化信息;
  2. edits文件: 存放HDFS文件系统的所有更新操作的路径,文件系统客户端执行的所有写操作首先会被记录到Edits文件中;

每次NameNode启动的时候都会将Fsimage文件读入内存,加载Edits里面的更新操作,保证内存中的元数据是最新的,同步的,可以看成NameNode启动的时候就将Fsimage和Edits文件进行了合并.

  1. seen_txid文件: 保存的是一个数字,就是最后一个edits_的数字;
  2. VERSION文件: 记录 NameNode节点对应的命名空间的id, HDFS 集群的唯一标识符cluster_id(这些标识符与DataNode一致, 用于防止 DataNode 意外注册到属于不同集群的不正确 NameNode。)

5.3.1, 使用oiv命令查看 fsimage文件

  1. oiv 和 oev

  2. 基本语法:

    hdfs oiv -p 文件类型 -i镜像文件 -o\转换后文件输出路径
  1. 案例实操:
  • 我们在xshell中使用 sz fsimage把该文件下载到本地, 用BowPad打开查看, 比如 我们要查看hdfs中/user/win10/abb.txt的目录信息:
  • 我们可以在其中的一个BLOCK中查找到这些文件或目录名.
  • 在fsimage靠后的位置存储着, 上面文件和目录的parent-child 归属关系

通过查看fsimage我们可以清楚的知道, NN只负责记录文件的元数据信息, 并不知道文件的具体存储位置, 而是由DN负责告知的.

5.3.2, 使用oev查看Edits文件

  1. 基本语法
hdfs oev -p 文件类型 -i 编辑日志 -o 转换后文件输出路径
  1. 案例实操
  • 我们先对HDFS执行一次操作, 这里我随便上传一个文件到HDFS中.
  • 提取日志文件到Windows中, 用BowPad打开.

  • 下面是我在操作HDFS上传文件后, edits中的记录
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<EDITS><EDITS_VERSION>-64</EDITS_VERSION><RECORD><OPCODE>OP_START_LOG_SEGMENT</OPCODE><DATA><TXID>1197</TXID></DATA></RECORD><RECORD><OPCODE>OP_ADD</OPCODE><DATA><TXID>1198</TXID><LENGTH>0</LENGTH><INODEID>16614</INODEID><PATH>/apiTest/text.txt._COPYING_</PATH><REPLICATION>3</REPLICATION><MTIME>1625197340573</MTIME><ATIME>1625197340573</ATIME><BLOCKSIZE>134217728</BLOCKSIZE><CLIENT_NAME>DFSClient_NONMAPREDUCE_947767106_1</CLIENT_NAME><CLIENT_MACHINE>192.168.182.100</CLIENT_MACHINE><OVERWRITE>true</OVERWRITE><PERMISSION_STATUS><USERNAME>win10</USERNAME><GROUPNAME>supergroup</GROUPNAME><MODE>420</MODE></PERMISSION_STATUS><ERASURE_CODING_POLICY_ID>0</ERASURE_CODING_POLICY_ID><RPC_CLIENTID>6b6c7166-b01f-42bd-a859-d5963b730497</RPC_CLIENTID><RPC_CALLID>3</RPC_CALLID></DATA></RECORD><RECORD><OPCODE>OP_ALLOCATE_BLOCK_ID</OPCODE><DATA><TXID>1199</TXID><BLOCK_ID>1073741964</BLOCK_ID></DATA></RECORD><RECORD><OPCODE>OP_SET_GENSTAMP_V2</OPCODE><DATA><TXID>1200</TXID><GENSTAMPV2>1140</GENSTAMPV2></DATA></RECORD><RECORD><OPCODE>OP_ADD_BLOCK</OPCODE><DATA><TXID>1201</TXID><PATH>/apiTest/text.txt._COPYING_</PATH><BLOCK><BLOCK_ID>1073741964</BLOCK_ID><NUM_BYTES>0</NUM_BYTES><GENSTAMP>1140</GENSTAMP></BLOCK><RPC_CLIENTID/><RPC_CALLID>-2</RPC_CALLID></DATA></RECORD><RECORD><OPCODE>OP_CLOSE</OPCODE><DATA><TXID>1202</TXID><LENGTH>0</LENGTH><INODEID>0</INODEID><PATH>/apiTest/text.txt._COPYING_</PATH><REPLICATION>3</REPLICATION><MTIME>1625197342135</MTIME><ATIME>1625197340573</ATIME><BLOCKSIZE>134217728</BLOCKSIZE><CLIENT_NAME/><CLIENT_MACHINE/><OVERWRITE>false</OVERWRITE><BLOCK><BLOCK_ID>1073741964</BLOCK_ID><NUM_BYTES>21359</NUM_BYTES><GENSTAMP>1140</GENSTAMP></BLOCK><PERMISSION_STATUS><USERNAME>win10</USERNAME><GROUPNAME>supergroup</GROUPNAME><MODE>420</MODE></PERMISSION_STATUS></DATA></RECORD><RECORD><OPCODE>OP_RENAME_OLD</OPCODE><DATA><TXID>1203</TXID><LENGTH>0</LENGTH><SRC>/apiTest/text.txt._COPYING_</SRC><DST>/apiTest/text.txt</DST><TIMESTAMP>1625197342157</TIMESTAMP><RPC_CLIENTID>6b6c7166-b01f-42bd-a859-d5963b730497</RPC_CLIENTID><RPC_CALLID>8</RPC_CALLID></DATA></RECORD>
</EDITS>

Q-A:

  1. NameNode如何确定下次集群启动时合并哪些信息?

    • 当前的 fsImage文件我们是已知的, fsImage的文件名也是已知的, 所以只需合并edits文件名中的序号大于 fsImage文件名序号的部分 edits文件即可.
  2. NN 和 2NN的差异文件?
    • edits-inprogress

5.4, CheckPoint时间设置

  1. 定时通常情况下,Secondary NameNode 每隔一小时执行一次

  2. 定次数一分钟检查一次操作次数,当操作次数达到一百万时,SecondaryNameNode执行一次;

六, DataNode

6.1, DataNode工作机制


  1. 一个数据块在DataNode上以文件形式存储在磁盘上,包括两个文件, 一个是数据本身, 另一个是元数据(.meta文件)(包括数据块的长度,块数据的校验和,以及时间戳);
  2. DataNode启动后向NameNode注册(报告块信息),NN返回注册成功的消息. 为避免中途宕机, DataNode会周期性(6小时)的向NameNode上传所有的块信息;
  3. 心跳(告诉NN本DN还活着)是每3秒一次,心跳返回结果带有NameNode给该DataNode的命令比如复制块数据到另一台机器,或是删除某个数据块. 如果超过十分钟没有收到某个DataNode的心跳(10分钟+ 30秒, 即十分钟再加上十次心跳),则认为该节点不可用;
  4. 集群运行中可以安全加入和退出一些机器.

6.2, 数据完整性

  • DataNode节点保证数据完整性的方法:

    1. 当DataNode读取Block的时候,它会计算CheckSum;
    2. 如果计算后的CheckSum, 与Block创建时值不一样,说明Block已经损坏;
    3. Client读取其他DataNode上的Block;
    4. 常见的校验算法 crc(32), md5, sha1;
    5. DataNode在其文件创建后周期验证ChechSum;

6.3 掉线时限参数设置

10分钟 + 30s


二, 大数据基础架构Hadoop-HDFS入门和基本操作(基本组成, Shell操作, API操作, 读写流程) hf相关推荐

  1. 大数据基础架构Hadoop,终于有人讲明白了

    导读:大数据正在成为经济社会发展的新的驱动力.随着云计算.移动互联网等网络新技术的应用和发展,社会信息化进程进入大数据时代,海量数据的产生与流转成为常态.而大数据技术也如雨后春笋般正在蓬勃发展中.Ha ...

  2. 大数据基础之Hadoop(一)—— Hadoop概述

    Hadoop系列 大数据基础之Hadoop(一)-- Hadoop概述 大数据基础之Hadoop(二)-- HDFS 大数据基础之Hadoop(三)-- MapReduce 大数据基础之Hadoop( ...

  3. 大数据基础之Hadoop(三)—— MapReduce

    作者:duktig 博客:https://duktig.cn (文章首发) 优秀还努力.愿你付出甘之如饴,所得归于欢喜. 本篇文章源码参看:https://github.com/duktig666/b ...

  4. 车联网大数据框架_大数据基础:ORM框架入门简介

    作为大数据开发技术者,需要掌握扎实的Java基础,这是不争的事实,所以对于Java开发当中需要掌握的重要框架技术,也需要有相应程度的掌握,比如说ORM框架.今天的大数据基础分享,我们就来具体讲一讲OR ...

  5. 大数据_07 【hadoop HDFS的shell命令操作】

    大数据_07 [hadoop HDFS的shell命令操作] 01 基本语法 02 常用普通命令实操 03 HDFS常用高级命令 04 HDFS适用场景 05 HDFS不适用场景 06 hdfs的安全 ...

  6. 大数据培训:Hadoop HDFS 实现原理

    一.HDFS体系结构 1.1 HDFS 简介 Hadoop分布式文件系统 (HDFS) 是运行在通用硬件(commodity hardware)上的分布式文件系统(Distributed File S ...

  7. 大数据技术之Hadoop(快速入门)

    目录 第一章 Hadoop概述 1.1 什么是Hadoop 1.2  Hadoop 产生背景 Hadoop之父:Doug cutting 1.3  Hadoop 三大发行版本 Hadoop 三大发行版 ...

  8. 大数据基础(hadoop环境搭建及使用)

    大数据 大数据概念 大数据特点(4V) Volume(大量) Velocity(高速) Variety(多样) Value(低价值密度) Hadoop Hadoop是什么 Hadoop 三大发行版本 ...

  9. 大数据技术之Hadoop(入门)概述、运行环境搭建、运行模式

    文章目录 1 Hadoop 概述 1.1 Hadoop 是什么 1.2 Hadoop 优势 1.3 Hadoop 组成(面试重点) 1.3.1 HDFS 架构概述 1.3.2 YARN 架构概述 1. ...

最新文章

  1. Apache Mina 介绍
  2. CentOs下php连mssql并配置unixODBC
  3. linux内存使用策略swap,Linux Swap使用分析
  4. php强制转成字符串,php怎么强制转成字符串
  5. 网盘运营太难了!百度网盘因“用户激励计划”起风波并致歉
  6. c 语言比较三个整数大小,C 语言 —— 比较三个整数的大小并从大到小输出
  7. PowerShell命令行窗口中设置环境变量 (简介,以及与cmd、shell、linux命令对比)
  8. python写股票指标_一文看懂KDJ指标及Python实现
  9. 啊哈C语言 第三章 【代码】【习题答案】
  10. 在arcgis中进行拓扑检查
  11. 华为价值评价体系的四个基本假设
  12. C++——以任意数为底的对数
  13. saas 系统租户个性化域名租户绑定自己域名的解决方案
  14. 村田 | 用于人机界面和生命体征检测的压电薄膜传感器
  15. 多个excel工作簿、工作表合并
  16. 前端寒假css(100-181)
  17. AD根据已有的PCB封装链接至原理图
  18. Python matplotpy颜色表(python画图常用颜色)
  19. 初级会计实务--第三章第四节、应交税费
  20. 100000行级别数据的 Excel 导入优化之路

热门文章

  1. mysql association_在mybatis的xml中添加association不生效
  2. libsvm的使用svm-scale和svm-train与svm-predict
  3. 谷歌浏览器 翻译无法使用的问题
  4. java堆栈总结、JVM
  5. 关于fastapi框架的异步
  6. android studio抛出,Android Studio升级到3.0,抛出Aapt2Exception异常
  7. 【树莓派】一、新坑入门-购买篇、基础配置篇
  8. 基于.net的大型web开源免费erp
  9. html手机陀螺仪,手机中的陀螺仪竟然也不值得信任
  10. MySQL Kill出现Killed死锁处理