谷歌技术"三宝"之BigTable

2023-11-01

2006年的OSDI有 两篇google的论文,分别是BigTable和Chubby。Chubby是一个分布式锁服务,基于Paxos算法;BigTable是一个用于管理结构化数据的分布式存储系统,构建在GFS、Chubby、SSTable等google技术之上。相当多的google应用使用了BigTable,比如Google Earth和Google Analytics,因此它和GFSMapReduce并称为谷歌技术"三宝"。

与GFS和MapReduce的论文相比,我觉得BigTable的论文难懂一些。一方面是因为自己对数据库不太了解,另一方面又是因为对数据库的理解局限于关系型数据库。尝试用关系型数据模型去理解BigTable就容易"走火入魔"。在这里推荐一篇文章:Understanding HBase and BigTable,相信这篇文章对理解BigTable/HBase的数据模型有很大帮助。

1 什么是BigTable

Bigtable是一个为管理大规模结构化数据而设计的分布式存储系统,可以扩展到PB级数据和上千台服务器。很多google的项目使用Bigtable存储数据,这些应用对Bigtable提出了不同的挑战,比如数据规模的要求、延迟的要求。Bigtable能满足这些多变的要求,为这些产品成功地提供了灵活、高性能的存储解决方案。

Bigtable看起来像一个数据库,采用了很多数据库的实现策略。但是Bigtable并不支持完整的关系型数据模型;而是为客户端提供了一种简单的数据模型,客户端可以动态地控制数据的布局和格式,并且利用底层数据存储的局部性特征。Bigtable将数据统统看成无意义的字节串,客户端需要将结构化和非结构化数据串行化再存入Bigtable。

下文对BigTable的数据模型和基本工作原理进行介绍,而各种优化技术(如压缩、Bloom Filter等)不在讨论范围。

2 BigTable的数据模型

Bigtable不是关系型数据库,但是却沿用了很多关系型数据库的术语,像table(表)、row(行)、column(列)等。这容易让读者误入歧途,将其与关系型数据库的概念对应起来,从而难以理解论文。Understanding HBase and BigTable是篇很优秀的文章,可以帮助读者从关系型数据模型的思维定势中走出来。

本质上说,Bigtable是一个键值(key-value)映射。按作者的说法,Bigtable是一个稀疏的,分布式的,持久化的,多维的排序映射。

先来看看多维、排序、映射。Bigtable的键有三维,分别是行键(row key)、列键(column key)和时间戳(timestamp),行键和列键都是字节串,时间戳是64位整型;而值是一个字节串。可以用 (row:string, column:string, time:int64)→string 来表示一条键值对记录。

行键可以是任意字节串,通常有10-100字节。行的读写都是原子性的。Bigtable按照行键的字典序存储数据。Bigtable的表会根据行键自动划分为片(tablet),片是负载均衡的单元。最初表都只有一个片,但随着表不断增大,片会自动分裂,片的大小控制在100-200MB。行是表的第一级索引,我们可以把该行的列、时间和值看成一个整体,简化为一维键值映射,类似于:

[javascript] view plaincopyprint?

  1. table{ 
  2. "1" : {sth.},//一行
  3. "aaaaa" : {sth.}, 
  4. "aaaab" : {sth.}, 
  5. "xyz" : {sth.}, 
  6. "zzzzz" : {sth.} 

列是第二级索引,每行拥有的列是不受限制的,可以随时增加减少。为了方便管理,列被分为多个列族(column family,是访问控制的单元),一个列族里的列一般存储相同类型的数据。一行的列族很少变化,但是列族里的列可以随意添加删除。列键按照family:qualifier格式命名的。这次我们将列拿出来,将时间和值看成一个整体,简化为二维键值映射,类似于:

[javascript] view plaincopyprint?

  1. table{ 
  2. // ...
  3. "aaaaa" : { //一行
  4. "A:foo" : {sth.},//一列
  5. "A:bar" : {sth.},//一列
  6. "B:" : {sth.} //一列,列族名为B,但是列名是空字串
  7.   }, 
  8. "aaaab" : { //一行
  9. "A:foo" : {sth.}, 
  10. "B:" : {sth.} 
  11.   }, 
  12. // ...

或者可以将列族当作一层新的索引,类似于:

[javascript] view plaincopyprint?

  1. table{ 
  2. // ...
  3. "aaaaa" : { //一行
  4. "A" : { //列族A
  5. "foo" : {sth.}, //一列
  6. "bar" : {sth.} 
  7.     }, 
  8. "B" : { //列族B
  9. "" : {sth.} 
  10.     } 
  11.   }, 
  12. "aaaab" : { //一行
  13. "A" : { 
  14. "foo" : {sth.}, 
  15.     }, 
  16. "B" : { 
  17. "" : "ocean"
  18.     } 
  19.   }, 
  20. // ...

时间戳是第三级索引。Bigtable允许保存数据的多个版本,版本区分的依据就是时间戳。时间戳可以由Bigtable赋值,代表数据进入Bigtable的准确时间,也可以由客户端赋值。数据的不同版本按照时间戳降序存储,因此先读到的是最新版本的数据。我们加入时间戳后,就得到了Bigtable的完整数据模型,类似于:

[javascript] view plaincopyprint?

  1. table{ 
  2. // ...
  3. "aaaaa" : { //一行
  4. "A:foo" : { //一列
  5.         15 : "y", //一个版本
  6.         4 : "m"
  7.       }, 
  8. "A:bar" : { //一列
  9.         15 : "d", 
  10.       }, 
  11. "B:" : { //一列
  12.         6 : "w"
  13.         3 : "o"
  14.         1 : "w"
  15.       } 
  16.   }, 
  17. // ...

查询时,如果只给出行列,那么返回的是最新版本的数据;如果给出了行列时间戳,那么返回的是时间小于或等于时间戳的数据。比如,我们查询"aaaaa"/"A:foo",返回的值是"y";查询"aaaaa"/"A:foo"/10,返回的结果就是"m";查询"aaaaa"/"A:foo"/2,返回的结果是空。

图1是Bigtable论文里给出的例子,Webtable表存储了大量的网页和相关信息。在Webtable,每一行存储一个网页,其反转的url作为行键,比如maps.google.com/index.html的数据存储在键为com.google.maps/index.html的行里,反转的原因是为了让同一个域名下的子域名网页能聚集在一起。图1中的列族"anchor"保存了该网页的引用站点(比如引用了CNN主页的站点),qualifier是引用站点的名称,而数据是链接文本;列族"contents"保存的是网页的内容,这个列族只有一个空列"contents:"。图1中"contents:"列下保存了网页的三个版本,我们可以用("com.cnn.www", "contents:", t5)来找到CNN主页在t5时刻的内容。

再来看看作者说的其它特征:稀疏,分布式,持久化。持久化的意思很简单,Bigtable的数据最终会以文件的形式放到GFS去。Bigtable建立在GFS之上本身就意味着分布式,当然分布式的意义还不仅限于此。稀疏的意思是,一个表里不同的行,列可能完完全全不一样。

3 支撑技术

Bigtable依赖于google的几项技术。用GFS来存储日志和数据文件;按SSTable文件格式存储数据;用Chubby管理元数据。

GFS参见谷歌技术"三宝"之谷歌文件系统。BigTable的数据和日志都是写入GFS的。

SSTable的全称是Sorted Strings Table,是一种不可修改的有序的键值映射,提供了查询、遍历等功能。每个SSTable由一系列的块(block)组成,Bigtable将块默认设为64KB。在SSTable的尾部存储着块索引,在访问SSTable时,整个索引会被读入内存。BigTable论文没有提到SSTable的具体结构,LevelDb日知录之四: SSTable文件这篇文章对LevelDb的SSTable格式进行了介绍,因为LevelDB的作者JeffreyDean正是BigTable的设计师,所以极具参考价值。每一个片(tablet)在GFS里都是按照SSTable的格式存储的,每个片可能对应多个SSTable。

Chubby是一种高可用的分布式锁服务,Chubby有五个活跃副本,同时只有一个主副本提供服务,副本之间用Paxos算法维持一致性,Chubby提供了一个命名空间(包括一些目录和文件),每个目录和文件就是一个锁,Chubby的客户端必须和Chubby保持会话,客户端的会话若过期则会丢失所有的锁。关于Chubby的详细信息可以看google的另一篇论文:The Chubby lock service for loosely-coupled distributed systems。Chubby用于片定位,片服务器的状态监控,访问控制列表存储等任务。

4 Bigtable集群

Bigtable集群包括三个主要部分:一个供客户端使用的库,一个主服务器(master server),许多片服务器(tablet server)。

正如数据模型小节所说,Bigtable会将表(table)进行分片,片(tablet)的大小维持在100-200MB范围,一旦超出范围就将分裂成更小的片,或者合并成更大的片。每个片服务器负责一定量的片,处理对其片的读写请求,以及片的分裂或合并。片服务器可以根据负载随时添加和删除。这里片服务器并不真实存储数据,而相当于一个连接Bigtable和GFS的代理,客户端的一些数据操作都通过片服务器代理间接访问GFS。

主服务器负责将片分配给片服务器,监控片服务器的添加和删除,平衡片服务器的负载,处理表和列族的创建等。注意,主服务器不存储任何片,不提供任何数据服务,也不提供片的定位信息。

客户端需要读写数据时,直接与片服务器联系。因为客户端并不需要从主服务器获取片的位置信息,所以大多数客户端从来不需要访问主服务器,主服务器的负载一般很轻。

5 片的定位

前面提到主服务器不提供片的位置信息,那么客户端是如何访问片的呢?来看看论文给的示意图,Bigtable使用一个类似B+树的数据结构存储片的位置信息。

首先是第一层,Chubby file。这一层是一个Chubby文件,它保存着root tablet的位置。这个Chubby文件属于Chubby服务的一部分,一旦Chubby不可用,就意味着丢失了root tablet的位置,整个Bigtable也就不可用了。

第二层是root tablet。root tablet其实是元数据表(METADATA table)的第一个分片,它保存着元数据表其它片的位置。root tablet很特别,为了保证树的深度不变,root tablet从不分裂。

第三层是其它的元数据片,它们和root tablet一起组成完整的元数据表。每个元数据片都包含了许多用户片的位置信息。

可以看出整个定位系统其实只是两部分,一个Chubby文件,一个元数据表。注意元数据表虽然特殊,但也仍然服从前文的数据模型,每个分片也都是由专门的片服务器负责,这就是不需要主服务器提供位置信息的原因。客户端会缓存片的位置信息,如果在缓存里找不到一个片的位置信息,就需要查找这个三层结构了,包括访问一次Chubby服务,访问两次片服务器。

6 片的存储和访问

片的数据最终还是写到GFS里的片在GFS里的物理形态就是若干个SSTable文件。图5展示了读写操作基本情况。

当片服务器收到一个写请求,片服务器首先检查请求是否合法。如果合法,先将写请求提交到日志去,然后将数据写入内存中的memtable。memtable相当于SSTable的缓存,当memtable成长到一定规模会被冻结,Bigtable随之创建一个新的memtable,并且将冻结的memtable转换为SSTable格式写入GFS,这个操作称为minor compaction。

当片服务器收到一个读请求,同样要检查请求是否合法。如果合法,这个读操作会查看所有SSTable文件和memtable的合并视图,因为SSTable和memtable本身都是已排序的,所以合并相当快。

每一次minor compaction都会产生一个新的SSTable文件,SSTable文件太多读操作的效率就降低了,所以Bigtable定期执行merging compaction操作,将几个SSTable和memtable合并为一个新的SSTable。BigTable还有个更厉害的叫major compaction,它将所有SSTable合并为一个新的SSTable。

遗憾的是,BigTable作者没有介绍memtable和SSTable的详细数据结构。

7 BigTable和GFS的关系

集群包括主服务器和片服务器,主服务器负责将片分配给片服务器,而具体的数据服务则全权由片服务器负责。但是不要误以为片服务器真的存储了数据(除了内存中memtable的数据),数据的真实位置只有GFS才知道,主服务器将片分配给片服务器的意思应该是,片服务器获取了片的所有SSTable文件名,片服务器通过一些索引机制可以知道所需要的数据在哪个SSTable文件,然后从GFS中读取SSTable文件的数据,这个SSTable文件可能分布在好几台chunkserver上。

8 元数据表的结构

元数据表(METADATA table)是一张特殊的表,它被用于数据的定位以及一些元数据服务,不可谓不重要。但是Bigtable论文里只给出了少量线索,而对表的具体结构没有说明。这里我试图根据论文的一些线索,猜测一下表的结构。首先列出论文中的线索:

  1. The METADATA table stores the location of a tablet under a row key that is an encoding of the tablet's table identifier and its end row.
  2. Each METADATA row stores approximately 1KB of data in memory(因为访问量比较大,元数据表是放在内存里的,这个优化在论文的locality groups中提到).This feature(将locality group放到内存中的特性) is useful for small pieces of data that are accessed frequently: we use it internally for the location column family in the METADATA table.
  3. We also store secondary information in the METADATA table, including a log of all events pertaining to each tablet(such as when a server begins 
    serving it).

第一条线索,元数据表的行键是由片所属表名的id和片最后一行编码而成,所以每个片在元数据表中占据一条记录(一行),而且行键既包含了其所属表的信息也包含了其所拥有的行的范围。譬如采取最简单的编码方式,元数据表的行键等于strcat(表名,片最后一行的行键)。

第二点线索,除了知道元数据表的地址部分是常驻内存以外,还可以发现元数据表有一个列族称为location,我们已经知道元数据表每一行代表一个片,那么为什么需要一个列族来存储地址呢?因为每个片都可能由多个SSTable文件组成,列族可以用来存储任意多个SSTable文件的位置。一个合理的假设就是每个SSTable文件的位置信息占据一列,列名为location:filename。当然不一定非得用列键存储完整文件名,更大的可能性是把SSTable文件名存在值里。获取了文件名就可以向GFS索要数据了。

第三个线索告诉我们元数据表不止存储位置信息,也就是说列族不止location,这些数据暂时不是咱们关心的。

通过以上信息,我画了一个简化的Bigtable结构图:

结构图以Webtable表为例,表中存储了网易、百度和豆瓣的几个网页。当我们想查找百度贴吧昨天的网页内容,可以向Bigtable发出查询Webtable表的(com.baidu.tieba, contents:, yesterday)。

假设客户端没有该缓存,那么Bigtable访问root tablet的片服务器,希望得到该网页所属的片的位置信息在哪个元数据片中。使用METADATA.Webtable.com.baidu.tieba为行键在root tablet中查找,定位到最后一个比它大的是METADATA.Webtable.com.baidu.www,于是确定需要的就是元数据表的片A。访问片A的片服务器,继续查找Webtable.com.baidu.tieba,定位到Webtable.com.baidu.www是比它大的,确定需要的是Webtable表的片B。访问片B的片服务器,获得数据。

这里需要注意的是,每个片实际都由若干SSTable文件和memtable组成,而且这些SSTable和memtable都是已排序的。这就导致查找片B时,可能需要将所有SSTable和memtable都查找一遍;另外客户端应该不会直接从元数据表获得SSTable的文件名,而只是获得片属于片服务器的信息,通过片服务器为代理访问SSTable。

参考文献

[1] Bigtable: A Distributed Storage System for Structured Data. In proceedings of OSDI'06.

[2] Understanding HBase and BigTable.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

谷歌技术"三宝"之BigTable 的相关文章

  • document.documentElement.scrollTop(获取滚动条位置)

    document documentElement scrollTop 收集关于scrollTop信息 要获取当前页面的滚动条纵坐标位置 用 document documentElement scrollTop 而不是 document bo
  • google Guava之EventBus

    文章目录 EventBus基本用法 1 创建Listener 2 创建EventBus并发送消息 Listener之间的继承关系 Subscriber 不同类型参数的Subscribe event 继承关系的event DeadEvent
  • 用mapreduce来操作hbase的两点优化

    用mapreduce来操作hbase的两点优化 用MR来对hbase的表数据进行分布式计算 有两点配置可以优化操作 提升性能 它们分别是 1 scan setCacheBlocks false 然后调用下面这句来初始化map任务 Table
  • 整合google,51ditu和mapbar的地图API

    http blog 163 com goodluck lq 126 blog static 63285386201001994058213
  • Google Maps API开发样例一则

    虽然还有一个多月的时间才过圣诞 但我还是早早的给大家送圣诞礼物了 那么圣诞礼物到底是什么呢 就是Google Maps API开发样例一则 不过这个礼物也不算是我送给大家的 而是谷歌地图中国的开发团队送给大家的 因为我也是从他们的Googl
  • Android控件之AutoCompleteTextView、MultiAutoCompleteTextView探究

    在Android中提供了两种智能输入框 它们是AutoCompleteTextView MultiAutoCompleteTextView 它们的功能大致一样 显示效果像Google搜索一样 当你在搜索框里输入一些字符时 至少两个字符 会自
  • 11款插件让你的Chrome成为全世界最好用的浏览器|Chrome插件推荐

    文章来源 知乎 收录于 风云社区 SCOEE 提供mac软件下载 更多专题 可关注小编 微学徒 查看我的文章 也可上 风云社区 SCOEE 查找和下载相关软件资源 一 综合类 新买苹果电脑 mac系统中小白应该了解哪些东西 Mac新手必看教
  • word2vector学习笔记(一)

    word2vector学习笔记 一 最近研究了一下google的开源项目word2vector http code google com p word2vec 其实这玩意算是神经网络在文本挖掘的一项成功应用 本文是看了论文 Distribu
  • 前置++和后置++的区别

    今天在阅读 google c 编程风格 的文档的时候 5 10 前置自增和自减 有一句话引起了我的注意 对于迭代器和其他模板对象使用前缀形式 i 的自增 自减运算符 理由是 前置自增 i 通常要比后置自增 i 效率更高 于是我查了查前置 和
  • 讲述IT人的程序人生,IT人心声,职业生涯,职场规划,程序员爱情优美文章155篇

    讲述IT人的程序人生 IT人心声 职业生涯 职场规划 程序员爱情优美文章155篇 来自 http www ithao123 com itlife 1 程序人生 程序 烟 我的人生2 程序人生 做技术 切不可沉湎于技术3 程序员 不得不习惯一
  • 各种虚拟机体验杂谈 --- 兼发布 google chrome os (chromiumos) vmware版本

    前两天赶时髦 把笔记本换上了win8 pro 换win8pro的原因 一个是价格真的很有诚意 另一个就是从DP版本开始就一直用 虽然兼容性问题多多 但作为宿主主机还行 而且xenclient也实在是让人窝火 号称裸机虚拟 其实硬盘速度慢如蜗
  • Google人机认证解决方法

    针对Chrome浏览器 下载gooreplacer 下载地址1 下载地址2 安装 gooreplacer crx Chrome无法从该网站添加应用 扩展程序和用户脚本 将 crx后缀改为 rar 之后开发者模式安装 重定向网址 重定向 将网
  • 隐藏Chrome浏览器新增标签页下方的快捷方式缩略图

    作为强迫症患者不喜欢搜索栏下方还有多余的东西 看着8个最近访问的快捷方式缩略图太不舒服了 在网上搜索了一堆方法 最有效的是替换一个PAK文件 但是过程有些繁琐 自己摸索后发现了一个简单的方法 在这记录一下以防自己忘记 查看设置中搜索引擎的地
  • java指纹识别+谷歌图片识别技术(采用Hash方法)

    转载自 http blog csdn net yjflinchong article details 7469213 java指纹识别 谷歌图片识别技术 前阵子在阮一峰的博客上看到了这篇 相似图片搜索原理 博客 就有一种冲动要将这些原理实现
  • 了解搜索引擎技术

    百度 Google搜索引擎核心技术是怎么实现的 搜索引擎 搜索引擎 search engine 是指根据一定的策略 运用特定的计算机程序搜集互联网上的信息 在对信息进行组织和处理后 并将处理后的信息显示给用户 是为用户提供检索服务的系统 全
  • 如何使用 cbt 从 BigTable 中删除带有前缀键的行范围

    看起来我可以用 cbt 读取带有前缀键的行 cbt project someproject instance someinstance read sometable prefix abc 但是如何使用 cbt 命令删除上述命令选择的那些行呢
  • NoSQL:MongoDB 或 BigTable 并不总是“可用”意味着什么

    阅读内森 赫斯特的著作NoSQL 系统视觉指南 http blog nahurst com visual guide to nosql systems 他包括CAP三角形 C一致性 A可用性 P分区容差 随着 SQL Server 成为AC
  • Hbase 和 BigTable 有什么区别?

    谁能告诉我 Apache HBase 数据库和 Bigtable 之间有什么区别 或者它们是相同的吗 如果有的话 哪一个支持关系 如果他们是大搜索者 有什么区别 它们很相似 但又不一样 Bigtable 最初于 2005 年发布 但并未发布
  • Bigtable CSV 导入

    我在多个文件 存储在存储桶中 中有一个大型 csv 数据集 gt 5TB 我需要将其导入到 Google Bigtable 中 这些文件的格式为 行键 s1 s2 s3 s4文本 整数 整数 整数 整数 hbase 有一个 importts
  • 在同一事务上读取和修改 - Bigtable

    我正在构建一个优惠券系统 并且正在使用 Bigtable 我的架构有两列 客户 ID 和优惠券代码 我想查询表以检查客户是否已存在 如果为真 则返回代码 如果为假 则使用 ID 修改客户 ID 单元格并返回代码 我看到 Bigtable 中

随机推荐

  • 【牛客SQL】SQL10 获取所有非manager的员工emp_no

    题目描述 描述 有一个员工表employees简况如下 有一个部门领导表dept manager简况如下 请你找出所有非部门领导的员工emp no 以上例子输出 示例1 输入 drop table if exists dept manage
  • 前端学习——jQuery基础

    一 引入jQuery的js文件 此处是下载好的jquery的js文件 也可以引入cdn 二 jQuery的入口函数 三 DOM对象和jQuery对象 div div 建一个盒子
  • react——state(状态机)

    h1 h1 h1 react state 状态 h1 p react把组件看成是一个状态机 state machines 通过与用户的交互 实现不同状态渲染UI 让用户界面和数据保持一致 p p react里 只需要更新组件的state 然
  • 【Qt教程】1.7 - Qt5带参数的信号、信号重载、带参数的槽函数、槽函数重载

    原理 与C 语法一致 信号 槽函数都可以发生重载 使其在名称不变的情况下 传递过程可以携带参数 示例说明 我们从一个最普通的信号槽工程中 来修改 对信号 槽进行重载 使信号 槽携带参数 1 普通信号 工程源码 widget h ifndef
  • rank、dense_rank、row_number函数的区别

    这四个 RANK DENSE RANK NTILE ROW NUMBER 函数 都是用来对数据库中的数据进行排名的 在他们的功能各有千秋 下面介绍一下这四个函数的功能和用法 首先创建一个Student表 CREATETABLEStudent
  • 树莓派安装opencv教程

    我使用的镜像版本为 Linux version 5 10 103 v7l dom buildbot arm linux gnueabihf gcc 8 Ubuntu Linaro 8 4 0 3ubuntu1 8 4 0 使用Python3
  • C++ 仿函数的分类

    一 概述 仿函数 functor 就是使一个类的使用看上去象一个函数 其实现就是类中实现一个operator 这个类就有了类似函数的行为 就是一个仿函数类了 有些功能的的代码 会在不同的成员函数中用到 想复用这些代码 1 公共的函数 可以
  • 普通人如何抓住AI这个风口

    随着科技的发展 人工智能 AI 已经成为当今社会的风口浪尖 越来越多的行业正在应用AI技术 新的职业和商业机会也随之出现 那么 作为普通人 我们应该如何抓住这个风口呢 来看看 AI硅基小助手 是如何解答的 1 学习AI相关技能 学习AI相关
  • Shiro和Spring Security的简单对比

    Shiro和Spring Security是Java中常用的两种安全认证框架 安全认证主要包括认证和授权鉴权两部分 认证指应用程序验证一个用户信息的过程 应用程序需要确认当前的用户是否是合法的用户 用户会向应用程序提供两部分数据 身份信息和
  • Java学习-冒泡排序

    冒泡排序 通俗的理解就是将一列无序的数字按照从大到小或者从小到大的顺序进行排序的一种简单的算法 在Java中一般是将数组使用冒泡排序的方法进行排序 大致原理是遍历数组元素 然后每两个之间进行比较 将较大值或者较小值按照自己想要的排序结果进行
  • YOLOV7调用本地USB摄像头和自己训练的权重文件实时检测目标

    作者新手 挣扎于毕业的菜鸡一枚 有问题欢迎讨论 最近在做课题时想直接调用本地摄像头来测试一下自己的训练结果 查到的文章多用到onnx openvino等格式转换部署 但作者没有这方面需求 折腾一会失败了 后来发现yolo系列自带了此功能 只
  • Linux xarges

    对于管道 之后的一部分命令可以用stdin进行输入 如 cat a grep test 但有些命令只能用参数形式 就要使用xargs了 xargs可以将stdin转化为参数 类似于find命令中的 exec选项 xargs也可以将单行或多行
  • 电赛经验分享

    2019 TI杯过程和经验分享 在这里我也是第一次写博客 看博客已经有一年多了吧 为什么要在这一次写博客呢 一是因为这一次比赛对我的影响很深 也算试一次经历和教训吧 二是因为最后一次参加TI杯大赛 在 比赛之前我们是做了充分的准备 把前两年
  • 如何用计算机名添加的打印机,如何添加打印机(如何在电脑上安装打印机)

    如何添加打印机 如何在电脑上安装打印机 平时在生活中 我们要将电子档的文件打印出来 都需要使用到打印机 传统的打印机都是以电脑为主 今天就教大家如何在电脑上安装打印机 电脑上安装打印机的详细步骤 1 双击打开桌面上的 控制面板 如果桌面上没
  • cadence布局布线常见问题详解

    cadence布局布线常见问题详解 1 怎样建立自己的元件库 建立了一个新的project后 画原理图的第一步就是先建立自己所需要的库 所采用的工具就是part developer 首先在建立一个存放元件库的目录 如mylib 然后用写字板
  • vue 前端调用摄像头上传压缩图片后端保存调用微信OCR识别身份证

    前端
  • iOS app签名机制

    前言 在移动开发中 iOS系统下的app和andorid系统下的app一个很大的区别是 android系统下 app的安装很方便 可以从多个应用商店下载 小米应用商店 华为应用商店 也可以直接下载apk的包安装 而在iOS系统下 对app的
  • 【CreateFile() Error 5】 权限问题解决

    CreateFile Error 5 权限问题解决 打开注册表 regedit HKEY LOCAL MACHINE Software Microsoft Windows CurrentVersion Policies System 修改这
  • git -C

    https git scm com docs git C
  • 谷歌技术"三宝"之BigTable

    谷歌技术 三宝 之BigTable 2006年的OSDI有 两篇google的论文 分别是BigTable和Chubby Chubby是一个分布式锁服务 基于Paxos算法 BigTable是一个用于管理结构化数据的分布式存储系统 构建在G