NameNode与DataNode的工作原理剖析

作者:尹正杰

版权声明:原创作品,谢绝转载!否则将追究法律责任。

一.HDFS写数据流程

1>.客户端通过Distributed FileSystem模块向NameNode请求上传文件,NameNode检查目标文件是否已存在,父目录是否存在。2>.NameNode返回是否可以上传。3>.客户端请求第一个 Block上传到哪几个DataNode服务器上。4>.NameNode返回3个DataNode节点,分别为DataNode1、DataNode2、DataNode3。5>.客户端通过FSDataOutputStream模块请求DataNode1上传数据,DataNode1收到请求会继续调用DataNode2,然后DataNode2调用DataNode3,将这个通信管道建立完成。6>.DataNode1、DataNode2、DataNode3逐级应答客户端。7>.客户端开始往DataNode1上传第一个Block(先从磁盘读取数据放到一个本地内存缓存),以Packet为单位,DataNode1收到一个Packet就会传给DataNode2,DataNode2传给DataNode3;DataNode1每传一个packet会放入一个应答队列等待应答。8>.当一个Block传输完成之后,客户端再次请求NameNode上传第二个Block的服务器。(重复执行3-7步)。

问第一个问题:请详细说明上面的第5步,DFSOutputStream是基于什么为单位上传数据的呢?

DFSOutputStream会将文件分割成packets数据包,然后将这些packets写到其内部的一个叫做data queue(数据队列)。data queue会向NameNode节点请求适合存储数据副本的DataNode节点的列表,然后这些DataNode之前生成一个Pipeline数据流管道,我们假设副本集参数被设置为3,那么这个数据流管道中就有三个DataNode节点。

问第二个问题: 在写数据的过程中,如果Pipeline数据流管道中的一个DataNode节点写失败了会发生什问题、需要做哪些内部处理呢?

首先,Pipeline数据流管道会被关闭,ack queue中的packets会被添加到data queue的前面以确保不会发生packets数据包的丢失;

接着,在正常的DataNode节点上的以保存好的block的ID版本会升级——这样发生故障的DataNode节点上的block数据会在节点恢复正常后被删除,失效节点也会被从Pipeline中删除;

最后,剩下的数据会被写入到Pipeline数据流管道中的其他两个节点中。

如果Pipeline中的多个节点在写数据是发生失败,那么只要写成功的block的数量达到dfs.replication.min(默认为1,Hadoop2.9.2版本已经将其更名为dfs.namenode.replication.min),那么就任务是写成功的,然后NameNode后通过一步的方式将block复制到其他节点,最后事数据副本达到dfs.replication参数配置的个数。

整个写流程如下:

第一步:

客户端调用DistributedFileSystem的create()方法,开始创建新文件:DistributedFileSystem创建DFSOutputStream,产生一个RPC调用,让NameNode在文件系统的命名空间中创建这一新文件;

第二步:

NameNode接收到用户的写文件的RPC请求后,首先要执行各种检查,如客户是否有相关的创佳权限和该文件是否已存在等,检查都通过后才会创建一个新文件,并将操作记录到编辑日志,然后DistributedFileSystem会将DFSOutputStream对象包装在FSDataOutStream实例中,返回客户端;否则文件创建失败并且给客户端抛IOException。

第三步:

客户端开始写文件:DFSOutputStream会将文件分割成packets数据包,然后将这些packets写到其内部的一个叫做data queue(数据队列)。data queue会向NameNode节点请求适合存储数据副本的DataNode节点的列表,然后这些DataNode之前生成一个Pipeline数据流管道,我们假设副本集参数被设置为3,那么这个数据流管道中就有三个DataNode节点。

第四步:

首先DFSOutputStream会将packets向Pipeline数据流管道中的第一个DataNode节点写数据,第一个DataNode接收packets然后把packets写向Pipeline中的第二个节点,同理,第二个节点保存接收到的数据然后将数据写向Pipeline中的第三个DataNode节点。

第五步:

DFSOutputStream内部同样维护另外一个内部的写数据确认队列——ack queue。当Pipeline中的第三个DataNode节点将packets成功保存后,该节点回向第二个DataNode返回一个确认数据写成功的信息,第二个DataNode接收到该确认信息后在当前节点数据写成功后也会向Pipeline中第一个DataNode节点发送一个确认数据写成功的信息,然后第一个节点在收到该信息后如果该节点的数据也写成功后,会将packets从ack queue中将数据删除。

在写数据的过程中,如果Pipeline数据流管道中的一个DataNode节点写失败了会发生什问题、需要做哪些内部处理呢?如果这种情况发生,那么就会执行一些操作:

首先,Pipeline数据流管道会被关闭,ack queue中的packets会被添加到data queue的最前面以确保不会发生packets数据包的丢失;

接着,在正常的DataNode节点上的以保存好的block的ID版本会升级——这样发生故障的DataNode节点上的block数据会在节点恢复正常后被删除,失效节点也会被从Pipeline中删除;

最后,剩下的数据会被写入到Pipeline数据流管道中的其他两个节点中。

如果Pipeline中的多个节点在写数据是发生失败,那么只要写成功的block的数量达到dfs.replication.min(默认为1),那么就任务是写成功的,然后NameNode后通过一步的方式将block复制到其他节点,最后使数据副本达到dfs.replication参数配置的个数。 因此,我们不得不怀疑该机制是否会导致一定的数据重复呢?

第六步:

完成写操作后,客户端调用close()关闭写操作,刷新数据;

第七步:

在数据刷新完后NameNode后关闭写操作流。到此,整个写操作完成。

参考链接:https://flyingdutchman.iteye.com/blog/1900536

Client是如何向Hadoop的HDFS中写数据的详解版本(烧脑版的解释,推荐大数据开发工程师阅读,大数据运维了解即可!)

上面我们说到的dfs.replication.min属性官方已经被更名为dfs.namenode.replication.min,因此我们直接去官方文档查阅dfs.replication.min肯能会查不到,更多参数变更请参考官方说明:http://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-common/DeprecatedProperties.html(不推荐使用的属性下表列出了此版本的Hadoop中不推荐使用的配置属性名称及其替换。)

二.机架感知

对于常见情况,当复制因子为3时,HDFS的放置策略是将一个副本放在本地机架中的一个节点上,另一个放在本地机架中的另一个节点上,最后一个放在不同机架中的另一个节点上。副本节点的选择大致为:1>.第一个副本在Client所处的节点上,如果客户端在集群外,随机选一个;2>.第二个副本和第一个副本位于相同机架,随机节点;3>.第三个部分位于不同几家,随机节点;

感兴趣的小伙伴可以参考官方文档:

参考一:http://hadoop.apache.org/docs/r2.9.2/hadoop-project-dist/hadoop-hdfs/HdfsDesign.html#Data_Replication参考二:http://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-common/RackAwareness.html

三.HDFS读数据流程

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

四.DataNode工作原理

1>.一个数据块在DataNode上以文件形式存储在磁盘上,包括两个文件,一个是数据本身,一个是元数据包括数据块的长度,块数据的校验和,以及时间戳。2>.DataNode启动后向NameNode注册,通过后,周期性(1小时)的向NameNode上报所有的块信息。3>.心跳是每3秒一次,心跳返回结果带有NameNode给该DataNode的命令如复制块数据到另一台机器,或删除某个数据块。如果超过10分钟没有收到某个DataNode的心跳,则认为该节点不可用。4>.集群运行中可以安全加入和退出一些机器。

五.数据完整性

1>.当DataNode读取block的时候,它会计算checksum;2>.如果计算后的checksum,与block创建时值不一样,说明block已经损坏;3>.client读取其他DataNode上的block;4>.datanode在其文件创建后周期验证checksum;

六.掉线时限参数设置

datanode进程死亡或者网络故障造成datanode无法与namenode通信,namenode不会立即把该节点判定为死亡,要经过一段时间,这段时间暂称作超时时长。HDFS默认的超时时长为10分钟+30秒。如果定义超时时间为timeout,则超时时长的计算公式为:“timeout = 2 * dfs.namenode.heartbeat.recheck-interval + 10 * dfs.heartbeat.interval ”。

而默认的"dfs.namenode.heartbeat.recheck-interval"大小为5分钟,"dfs.heartbeat.interval"默认为3秒。需要注意的是hdfs-site.xml配置文件中"heartbeat.recheck.interval"的单位为毫秒,"dfs.heartbeat.interval"的单位为秒。

[root@node101.yinzhengjie.org.cn ~]# cat /yinzhengjie/softwares/hadoop-2.9.2/etc/hadoop/hdfs-site.xml<?xml version="1.0" encoding="UTF-8"?>

dfs.namenode.checkpoint.period

3600

dfs.namenode.name.dir

/data/hadoop/hdfs/dfs/name

dfs.replication

2

dfs.namenode.heartbeat.recheck-interval

300000

dfs.heartbeat.interval

3

[root@node101.yinzhengjie.org.cn~]#

[root@node101.yinzhengjie.org.cn ~]# cat /yinzhengjie/softwares/hadoop-2.9.2/etc/hadoop/hdfs-site.xml

七.DataNode的目录结构

和NameNode不同的是,DataNode的存储目录是初始阶段自动创建的,不需要额外格式化。

1>.查看DataNode目录下对应的版本号("${hadoop.tmp.dir}/dfs/data/current/VERSION")

[root@node101.yinzhengjie.org.cn ~]# ll /data/hadoop/hdfs/dfs/data/current/total8drwx------. 4 root root 4096 Apr 12 18:44 BP-883662044-172.30.1.101-1555064443805

-rw-r--r--. 1 root root 229 Apr 12 18:44VERSION

[root@node101.yinzhengjie.org.cn~]#

[root@node101.yinzhengjie.org.cn ~]# ll /data/hadoop/hdfs/dfs/data/current/

[root@node101.yinzhengjie.org.cn ~]# cat /data/hadoop/hdfs/dfs/data/current/VERSION

#Fri Apr12 18:44:23 CST 2019storageID=DS-e181274d-eace-44c1-b001-ac26fbfa3f8c       #存储id号

clusterID=CID-e7603940-eaba-4ce6-9ecd-3a449027b432       #集群id,全局唯一

cTime=0                                #标记了datanode存储系统的创建时间,对于刚刚格式化的存储系统,这个属性为0;但是在文件系统升级之后,改值会更新到新的时间戳。datanodeUuid=a7c28347-2816-47ee-a3f9-153d11e162bf       #datanode的唯一标识码

storageType=DATA_NODE                        #存储类型

layoutVersion=-57                          #一般情况下是一个负数,通常只有HDFS增加新特性时才会更新这个版本号。[root@node101.yinzhengjie.org.cn~]#

[root@node101.yinzhengjie.org.cn~]#

[root@node102.yinzhengjie.org.cn ~]# cat /data/hadoop/hdfs/dfs/data/current/VERSION

#Fri Apr12 18:44:23 CST 2019storageID=DS-e181274d-eace-44c1-b001-ac26fbfa3f8c

clusterID=CID-e7603940-eaba-4ce6-9ecd-3a449027b432

cTime=0datanodeUuid=a7c28347-2816-47ee-a3f9-153d11e162bf

storageType=DATA_NODE

layoutVersion=-57[root@node102.yinzhengjie.org.cn~]#

[root@node102.yinzhengjie.org.cn ~]# cat /data/hadoop/hdfs/dfs/data/current/VERSION

[root@node103.yinzhengjie.org.cn ~]# cat /data/hadoop/hdfs/dfs/data/current/VERSION

#Fri Apr12 18:44:23 CST 2019storageID=DS-e181274d-eace-44c1-b001-ac26fbfa3f8c

clusterID=CID-e7603940-eaba-4ce6-9ecd-3a449027b432

cTime=0datanodeUuid=a7c28347-2816-47ee-a3f9-153d11e162bf

storageType=DATA_NODE

layoutVersion=-57[root@node103.yinzhengjie.org.cn~]#

[root@node103.yinzhengjie.org.cn ~]# cat /data/hadoop/hdfs/dfs/data/current/VERSION

2>.查看DataNode目录下对应数据块的版本号("${hadoop.tmp.dir}/dfs/data/current/BP-*/current/VERSION")

[root@node101.yinzhengjie.org.cn ~]# cat /data/hadoop/hdfs/dfs/data/current/BP-883662044-172.30.1.101-1555064443805/current/VERSION

#Fri Apr12 18:44:23 CST 2019namespaceID=1161472027                     #是datanode首次访问namenode的时候从namenode处获取的storageID对每个datanode来说是唯一的(但对于单个datanode中所有存储目录来说则是相同的),namenode可以用这个属性来区分不同datanode。cTime=1555064443805                       #标记了datanode存储系统的创建时间,对于刚刚格式化的存储系统,这个属性为0;但是在文件系统升级之后,该值会更新到新的时间戳。blockpoolID=BP-883662044-172.30.1.101-1555064443805    #标识一个block pool,并且是跨集群的全局唯一。当一个新的NameSpace被创建的时候(format过程的一部分)会创建并持久化一个唯一ID,在创建过程构建全局唯一的BlockPoolID此人为的配置更可靠一些。NameNode将BlockPoolID持久化到磁盘中,在后续的启动过程中,会再次load并使用。layoutVersion=-57                        #改值是一个负整数。通常只有HDFS增加新特性时才会更新这个版本号。[root@node101.yinzhengjie.org.cn~]#

[root@node101.yinzhengjie.org.cn~]#

[root@node102.yinzhengjie.org.cn ~]# cat /data/hadoop/hdfs/dfs/data/current/BP-883662044-172.30.1.101-1555064443805/current/VERSION

#Fri Apr12 18:44:23 CST 2019namespaceID=1161472027cTime=1555064443805blockpoolID=BP-883662044-172.30.1.101-1555064443805layoutVersion=-57[root@node102.yinzhengjie.org.cn~]#

[root@node102.yinzhengjie.org.cn~]#

[root@node102.yinzhengjie.org.cn ~]# cat /data/hadoop/hdfs/dfs/data/current/BP-883662044-172.30.1.101-1555064443805/current/VERSION

[root@node103.yinzhengjie.org.cn ~]# cat /data/hadoop/hdfs/dfs/data/current/BP-883662044-172.30.1.101-1555064443805/current/VERSION

#Fri Apr12 18:44:23 CST 2019namespaceID=1161472027cTime=1555064443805blockpoolID=BP-883662044-172.30.1.101-1555064443805layoutVersion=-57[root@node103.yinzhengjie.org.cn~]#

[root@node103.yinzhengjie.org.cn ~]# cat /data/hadoop/hdfs/dfs/data/current/BP-883662044-172.30.1.101-1555064443805/current/VERSION

八.DataNode多目录配置(我们在主节点做了任何修改后,最好同步到整个集群中去,否则可能会导致部分节点启动失败!)

DataNode也可以配置成多个目录,每个目录存储的数据不一样。即:数据不是副本!切记,DataNode的多目录配置和NameNode的多目录配置效果是不一样的! NameNode配置多目录是为了把元数据存储多份,达到配置备份的目的。

关于已经有数据的HDFS集群中,配置案例如下:

[root@node101.yinzhengjie.org.cn ~]# cat /yinzhengjie/softwares/hadoop-2.9.2/etc/hadoop/core-site.xml<?xml version="1.0" encoding="UTF-8"?>

fs.defaultFS

hdfs://node101.yinzhengjie.org.cn:8020

hadoop.tmp.dir

/data/hadoop/hdfs

[root@node101.yinzhengjie.org.cn~]#

[root@node101.yinzhengjie.org.cn ~]# cat /yinzhengjie/softwares/hadoop-2.9.2/etc/hadoop/core-site.xml

[root@node101.yinzhengjie.org.cn ~]# cat /yinzhengjie/softwares/hadoop-2.9.2/etc/hadoop/hdfs-site.xml<?xml version="1.0" encoding="UTF-8"?>

dfs.namenode.checkpoint.period

3600

dfs.namenode.name.dir

file:///${hadoop.tmp.dir}/dfs/namenode1,file:///${hadoop.tmp.dir}/dfs/namenode2,file:///${hadoop.tmp.dir}/dfs/namenode3

dfs.datanode.data.dir

file:///${hadoop.tmp.dir}/dfs/data1,file:///${hadoop.tmp.dir}/dfs/data2

dfs.replication

2

dfs.namenode.heartbeat.recheck-interval

300000

dfs.heartbeat.interval

3

[root@node101.yinzhengjie.org.cn~]#

[root@node101.yinzhengjie.org.cn ~]# cat /yinzhengjie/softwares/hadoop-2.9.2/etc/hadoop/hdfs-site.xml

[root@node101.yinzhengjie.org.cn ~]# scp -r /yinzhengjie/softwares/hadoop-2.9.2/ node102.yinzhengjie.org.cn:/yinzhengjie/softwares/

[root@node101.yinzhengjie.org.cn ~]# scp -r /yinzhengjie/softwares/hadoop-2.9.2/ node102.yinzhengjie.org.cn:/yinzhengjie/softwares/        #我们需要把配置同步到其他节点中

[root@node101.yinzhengjie.org.cn ~]# scp -r /yinzhengjie/softwares/hadoop-2.9.2/ node103.yinzhengjie.org.cn:/yinzhengjie/softwares/

[root@node101.yinzhengjie.org.cn ~]# scp -r /yinzhengjie/softwares/hadoop-2.9.2/ node103.yinzhengjie.org.cn:/yinzhengjie/softwares/

[root@node101.yinzhengjie.org.cn ~]# cat /data/hadoop/hdfs/dfs/data1/current/VERSION

#Mon Apr15 15:47:43 CST 2019storageID=DS-a29dd65a-de0e-44b1-b51b-5d537f0ab7f1

clusterID=CID-377f58b3-a3a2-4ca7-bf72-7d47714cf9cd

cTime=0datanodeUuid=d1d3a605-0218-42b9-9638-255343195296storageType=DATA_NODE

layoutVersion=-57[root@node101.yinzhengjie.org.cn~]#

[root@node101.yinzhengjie.org.cn ~]# cat /data/hadoop/hdfs/dfs/data1/current/VERSION                 #为什么我们说配置存储的多目录原因是数据是存储在不同的目录的并么有备份,因为他们的storageID不同!

[root@node101.yinzhengjie.org.cn ~]# cat /data/hadoop/hdfs/dfs/data2/current/VERSION

#Mon Apr15 15:47:43 CST 2019storageID=DS-9f2fa0b3-e9d7-4743-a9e8-ff2d81370200

clusterID=CID-377f58b3-a3a2-4ca7-bf72-7d47714cf9cd

cTime=0datanodeUuid=d1d3a605-0218-42b9-9638-255343195296storageType=DATA_NODE

layoutVersion=-57[root@node101.yinzhengjie.org.cn~]#

[root@node101.yinzhengjie.org.cn ~]# cat /data/hadoop/hdfs/dfs/data2/current/VERSION

[root@node102.yinzhengjie.org.cn ~]# cat /data/hadoop/hdfs/dfs/data1/current/VERSION

#Mon Apr15 15:47:43 CST 2019storageID=DS-053dada1-36dd-490b-a1d5-1a523bcfc6f3

clusterID=CID-377f58b3-a3a2-4ca7-bf72-7d47714cf9cd

cTime=0datanodeUuid=b43206d7-eb51-48b5-b269-6bd6502b5f9f

storageType=DATA_NODE

layoutVersion=-57[root@node102.yinzhengjie.org.cn~]#

[root@node102.yinzhengjie.org.cn ~]# cat /data/hadoop/hdfs/dfs/data1/current/VERSION

[root@node102.yinzhengjie.org.cn ~]# cat /data/hadoop/hdfs/dfs/data2/current/VERSION

#Mon Apr15 15:47:43 CST 2019storageID=DS-28a3e682-3ae8-4ce2-abf5-6691b669ef1a

clusterID=CID-377f58b3-a3a2-4ca7-bf72-7d47714cf9cd

cTime=0datanodeUuid=b43206d7-eb51-48b5-b269-6bd6502b5f9f

storageType=DATA_NODE

layoutVersion=-57[root@node102.yinzhengjie.org.cn~]#

[root@node102.yinzhengjie.org.cn ~]# cat /data/hadoop/hdfs/dfs/data2/current/VERSION

[root@node103.yinzhengjie.org.cn ~]# cat /data/hadoop/hdfs/dfs/data1/current/VERSION

#Mon Apr15 15:47:43 CST 2019storageID=DS-e55b7230-fc9b-4122-a19d-30cb5855d455

clusterID=CID-377f58b3-a3a2-4ca7-bf72-7d47714cf9cd

cTime=0datanodeUuid=ed3bea6a-f5cd-45e9-8302-6de2106ec863

storageType=DATA_NODE

layoutVersion=-57[root@node103.yinzhengjie.org.cn~]#

[root@node103.yinzhengjie.org.cn ~]# cat /data/hadoop/hdfs/dfs/data1/current/VERSION

[root@node103.yinzhengjie.org.cn ~]# cat /data/hadoop/hdfs/dfs/data2/current/VERSION

#Mon Apr15 15:47:43 CST 2019storageID=DS-3d59f0c6-ebbf-4f3d-b470-256c01a200d4

clusterID=CID-377f58b3-a3a2-4ca7-bf72-7d47714cf9cd

cTime=0datanodeUuid=ed3bea6a-f5cd-45e9-8302-6de2106ec863

storageType=DATA_NODE

layoutVersion=-57[root@node103.yinzhengjie.org.cn~]#

[root@node103.yinzhengjie.org.cn ~]# cat /data/hadoop/hdfs/dfs/data2/current/VERSION

九.Hadoop的集群管理之服役和退役

namenode和datanode工作机制_NameNode与DataNode的工作原理剖析相关推荐

  1. Secondary Namenode的Check point机制以及Namenode、Datanode工作机制说明

    目录 前言: 1.NameNode的工作机制 2.DataNode的工作机制 3.Secondary Namenode的Check point机制 目录 前言: 在说明checkpoint机制之前,先 ...

  2. Hadoop生态圈(十三)- Namenode元数据管理及各组件工作机制

    目录 前言 1. Namenode元数据管理 1.1 元数据是什么 1.2 元数据管理概述 1.2.1 内存元数据 1.2.2 磁盘元数据 1.2.2.1 fsimage内存镜像文件 1.2.2.2 ...

  3. 深入浅出之Smarty模板引擎工作机制(一)

    深入浅出Smarty模板引擎工作机制,我们将对比使用smarty模板引擎和没使用smarty模板引擎的两种开发方式的区别,并动手开发一个自己的模板引擎,以便加深对smarty模板引擎工作机制的理解. ...

  4. JavaWeb技术内幕二:Java IO工作机制

    IO问题是当今web应用所面临的主要问题之一,因为数据在网络中随处流动,在这个流动过程中都涉及IO问题,并且大部分应用的瓶颈都是IO瓶颈. 本章将从IO的角度出发,介绍IO类库的基本架构,磁盘IO的工 ...

  5. Android视图工作机制之measure、layout、draw

    前言 自定义View一直是初学者们最头疼的事情,因为他们并没有了解到真正的实现原理就开始试着做自定义View,碰到很多看不懂的代码只能选择回避,做多了会觉得很没自信.其实只要了解了View的工作机制后 ...

  6. 深入浅出之Smarty模板引擎工作机制(二)

    源代码下载地址:深入浅出之Smarty模板引擎工作机制 接下来根据以下的Smarty模板引擎原理流程图开发一个自己的模板引擎用于学习,以便加深理解. Smarty模板引擎的原理,其实是这么一个过程: ...

  7. Smarty模板引擎工作机制(一)

    深入浅出Smarty模板引擎工作机制,我们将对比使用smarty模板引擎和没使用smarty模板引擎的两种开发方式的区别,并动手开发一个自己的模板引擎,以便加深对smarty模板引擎工作机制的理解. ...

  8. Smarty模板引擎工作机制(二)

    源代码下载地址:深入浅出之Smarty模板引擎工作机制 接下来根据以下的Smarty模板引擎原理流程图开发一个自己的模板引擎用于学习,以便加深理解. Smarty模板引擎的原理,其实是这么一个过程: ...

  9. Android进阶——Android视图工作机制之measure、layout、draw

    前言 自定义View一直是初学者们最头疼的事情,因为他们并没有了解到真正的实现原理就开始试着做自定义View,碰到很多看不懂的代码只能选择回避,做多了会觉得很没自信.其实只要了解了View的工作机制后 ...

最新文章

  1. express中放置静态文件
  2. C#调用API向外部程序发送数据(转载)
  3. python计算器基础知识_Python基础(一):将Python当做计算器、编程的第一步
  4. Android之AsyncTask两种线程池分析和总结
  5. 【JAVA笔记——道】Hibernate 线程本地化基础篇
  6. MyBatis 的 4 个妙用,别再踩坑了!
  7. Android 判定手机是否root
  8. Atitit 图像处理和计算机视觉的分类 三部分 图像处理 图像分析 计算机视觉
  9. 利用PLTS从F域Export出T域数据指南
  10. 有道惠惠购物助手和如意淘使用比较
  11. java微信公众号开发一:服务器信息配置
  12. 如何在macOS中重置字体集
  13. android 模拟器使用intel硬件加速
  14. 《Android Studio 实战》总结一
  15. 一款仿网易云音乐Java开源系统(附源码)
  16. python简单的绘制折现图
  17. 计算机毕业设计Java个人理财系统(源码+系统+mysql数据库+lW文档)
  18. DWZ富客户端框架使用手册
  19. BLDC 6步换相 simulink
  20. 游戏开发常用工具总结

热门文章

  1. 能够研制超级计算机的国家,我国成为世界上第 个能够研制千万亿次超级计算机的国家.------ [ ] A.三 B.二 C.一 D.四...
  2. 高楼之下,尸骨为基:移动互联网的七宗败案
  3. 因为在清除过期缓存条目后可用空间仍不足 - 请考虑增加缓存的最大空间。
  4. echart-水球图
  5. (转)2008年精典骗术, 2009年你还会上当吗?
  6. 清理计算机磁盘碎片,电脑磁盘碎片清理我帮你
  7. 肖 清华计算机系 北大生命科学,7个清华北大,11+复旦交大,后续还有一大波浙大……他们都是同班同学!...
  8. keil4怎么移植其他人的程序_遗传性脱发怎么自救,头发稀少掉发的原因?怎么办?...
  9. 治头发稀少哪个方法好 六个有效的生发方法
  10. Android耳机线控-播放/暂停/上一曲/下一曲