文章目录
摘要
1. 简介
2. 数据模型
3. API
4. 构成模块
5. 实现
5.1 分片位置
5.2 片分配
5.3 片服务器
5.4 压缩
6. 改进
6.1 位置分组
6.2 压缩
6.3 为读取性能缓存
6.4 布隆过滤器
6.5 提交日志实现
6.6 加快分片的恢复速度
6.7 利用不变性
7. 性能评估
8. 实际应用
8.1 Google Analytics
8.2 Google Earth
8.3 Personalized Search
9. 教训
10. 相关工作
11. 总结
致谢
参考文献
摘要
Bigtable是一个用于管理结构化数据的分布式存储系统,旨在扩展到非常大的规模:数千个商用服务器上的数PB数据。Google的许多项目都在Bigtable中存储数据,包括网络索引,Google Earth和Google Finance。这些应用对Bigtable提出了非常不同的要求,包括数据大小(从URL到网页到卫星图像)和延迟要求(从后端批处理到实时数据服务)。尽管有这些不同的需求,但Bigtable已成功为所有这些Google产品提供灵活、高性能的解决方案。在本文中,我们描述了Bigtable提供的简单数据模型,它为客户提供了对数据布局和格式的动态控制,并描述了Bigtable的设计和实现。
1. 简介
在过去两年半的时间里,我们设计、实施并部署了一个叫Bigtable的分布式存储系统,用于管理Google的结构化数据。Bigtable旨在可靠地扩展到数PB的数据和数千台计算机。Bigtable实现了多个目标:广泛的适用性、可扩展性、高性能和高可用性。Bigtable被超过60个Google产品和项目使用,包括Google Analytics、Google Finance、Orkut、Personalized Search、Writely和Google Earth。这些产品使用Bigtable来处理各种要求苛刻的工作,从面向吞吐量的批处理作业到对延迟敏感的数据服务,再到终端用户。这些产品使用的Bigtable集群涵盖了从少量到数千台服务器的各种配置,并可存储高达数百TB的数据。
在很多方面,Bigtable类似于数据库:它与数据库共享许多实现策略。并行数据库[14]和内存数据库[13]已经实现了可扩展性和高性能,但Bigtable提供了与这些系统不同的接口。Bigtable不支持完整的关系数据模型; 相反,它为客户提供了一个简单的数据模型,支持对数据布局和格式的动态控制,并允许客户端推断数据在底层存储中的位置属性。使用可以是任意字符串的行名和列名来索引数据。Bigtable也将数据视为未解释的字符串,尽管客户端经常将各种形式的结构化和半结构化数据序列化为这些字符串。客户端可以通过在模式中仔细选择来控制数据的位置。最后,Bigtable模式参数允许客户端动态控制是从内存还是从磁盘提供数据。
第2节更详细地描述了数据模型,第3节提供了客户端API的概述。第4节简要介绍了Bigtable所依赖的底层Google基础设施。第5节描述了Bigtable实现的基本原理,第6节描述了我们为提高Bigtable性能所做的一些改进。第7节提供了Bigtable的性能测试。我们在第8节中描述了几个关于如何在Google中使用Bigtable的示例,并在第9节中讨论了我们设计和支持Bigtable时学到的一些经验教训。最后,第10节描述了相关工作,第11节介绍了我们的总结。
2. 数据模型
Bigtable是一个稀疏的、分布式的、持久化的多维有序映射。映射由行键、列键和时间戳索引; 映射中的每个值都是未解释的字节数组。
(row:string, column:string, time:int64) -> string
在研究了类Bigtable系统的各种潜在用途后,我们确定了这个数据模型。作为推动我们的一些设计决策的一个具体例子:假设我们想要保留会被许多不同项目使用的大量网页和相关信息的副本; 让我们将这个特定的表称为Webtable。在Webtable中,我们将URL用作行键,将网页的各个方面用作列名,并将网页的内容存储在contents列中:列在抓取网页时的时间戳下,如图1所示。
2.1 行
表中的行键是任意字符串(当前最大为64KB,但对于大多数用户来说,10-100字节是典型的大小)。单个行键下的每次数据读取或写入都是原子的(无论行中读取或写入的不同列的数量如何),这一设计决策使客户端更容易在出现并发更新到同一行时推断系统的行为。
Bigtable维护按行键的字典顺序排列的数据。表的行范围是动态分区的。每个行范围称为一个分片,它是分配和负载均衡的单位。结果,小的行范围的读取是高效的,并且通常只需要与少量机器通信。客户端可以通过选择行键来利用此特性,以便它们获得数据访问的好的定位。例如,在Webtable中,通过反转的URL的主机名组成,将同一域名中的页面分组在一起成为连续的行。例如,我们会在键com.google.maps/index.html
下存储maps.google.com/index.html
的数据。将来自同一域名的页面存储在彼此附近使得一些主机和域名分析更高效。
2.2 列族
列键被分组后的集合称为称为列族,这构成了访问控制的基本单元。存储在列族中的所有数据通常具有相同的类型(我们将同一列族中的数据压缩在一起)。必须先创建列族,然后才能将数据存储在该族中的任何列键下; 在创建列族之后,可以使用列族中的任何列键。我们的意图是表中不同列族的数量很小(最多数百个),并且族在运行期间很少发生变化。相反,表可能具有无限数量的列。
使用以下语法命名列键:family:qualifier
。列族名称必须是可打印的,但限定符可以是任意字符串。Webtable的示例列族是language,它存储编写网页的语言。我们在language列族中只使用一个列键,它存储每个网页的语言ID。该表的另一个有用的列族是anchor; 此列族中的每个列键代表一个锚点,如图1所示。限定符是引用站点的名称; 单元内容是链接文本。
访问控制以及磁盘和内存统计都在列族级别执行。在我们的Webtable示例中,这些控制允许我们管理几种不同类型的应用:一些用于添加新的基础数据,一些用于读取基础数据并创建派生列族,还有一些仅允许查看现有数据(出于隐私原因甚至可能不会查看所有现有列族)。
2.3 时间戳
Bigtable中的每个单元都可以包含相同数据的多个版本; 这些版本由时间戳索引。Bigtable时间戳是64位整数。它们可以由Bigtable分配,在这种情况下,它们以微秒表示“实时”,或由客户端应用显式分配。需要避免冲突的应用必须自己生成唯一的时间戳。以时间戳递减的顺序存储单元的不同版本,以便可以首先读取最新版本。
为了方便版本化数据的管理,我们支持两个列族设置,告诉Bigtable自动垃圾收集单元版本。客户端可以指定仅保留单元的最后n个版本,或者仅保留足够新的版本(例如,仅保留在过去七天中写入的值)。
在我们的Webtable示例中,我们将存储在contents列已爬取网页的时间戳设置为:实际爬取这些页面版本的时间。上面描述的垃圾收集机制让我们能只保留每个页面的最新三个版本。
3. API
Bigtable API提供了创建和删除表和列族的功能。它还提供用于更改集群、表和列族元数据的功能,例如访问控制权限。
客户端应用程序可以在Bigtable中写入或删除值,从单个行中查找值,或迭代表中数据的子集。图2显示了使用RowMutation抽象来执行一系列更新的C ++代码。(不相关的细节被省略以保持示例简短。)调用Apply对Webtable执行原子变更:它向www.cnn.com
添加一个锚并删除一个不同的锚。
图3显示了使用Scanner抽象迭代特定行中所有锚点的C ++代码。客户端可以迭代多个列族,并且有几种机制可以生成限制的扫描行、列和时间戳。例如,我们可以将上面的扫描限制为仅生成其列与正则表达式锚点:*.cnn.com
匹配的锚点,或者仅生成其时间戳落在当前时间的十天内的锚点。
Bigtable支持其他一些功能,允许用户以更复杂的方式操作数据。首先,Bigtable支持单行事务,可用于对存储在单行键下的数据执行原子读-修改-写序列操作。Bigtable目前不支持跨行的常规事务,但它提供了一个接口,用于在客户端上批量跨行写入。其次,Bigtable允许将单元用作整数计数器。最后,Bigtable支持在服务器的地址空间中执行客户端提供的脚本。这些脚本是用Google开发的一种语言编写的,用于处理称为Sawzall的数据[28]。目前,我们基于Sawzall的API不允许客户端脚本写回Bigtable,但它允许各种形式的数据转换,基于任意表达式的过滤以及通过各种运算符进行汇总。
Bigtable可以与MapReduce[12]一起使用,MapReduce是一个在Google中用于运行开发的大规模并行计算的框架。我们编写了一组包装器,允许Bigtable既可以用作输入源,也可以用作MapReduce作业的输出目标。
4. 构成模块
Bigtable建立在其他几个Google基础设施上。Bigtable使用分布式Google文件系统(GFS)[17]来存储日志和数据文件。Bigtable集群通常在运行有各种其他分布式应用的共享计算机池中运行,并且Bigtable进程通常与来自其他应用的进程共享相同的计算机。Bigtable依赖于集群管理系统来调度作业、管理共享机器上的资源、处理机器故障以及监视机器状态。
Google SSTable文件格式在内部用于存储Bigtable数据。SSTable提供从键到值的持久的、有序不可变的映射,其中键和值都是任意字节串。提供了查找与指定键相关联的值的操作,并迭代指定键范围内的所有键/值对。在内部,每个SSTable都包含一系列块(通常每个块的大小为64KB,但这是可配置的)。块索引(存储在SSTable的末尾)用于定位块; 打开SSTable时,索引将加载到内存中。可以使用单个磁盘搜索执行查找:我们首先通过在内存索引中执行二分查找,然后从磁盘读取相应的块来找到适当的块。可选地,SSTable可以完全映射到内存中,这允许我们在不接触磁盘的情况下执行查找和扫描。
Bigtable依赖于一种名为Chubby[8]的高可用和持久化的分布式锁服务。Chubby服务由五个活跃副本组成,其中一个被选为主服务器并主动服务请求。当大多数副本正在运行并且可以相互通信时,该服务是活着的。Chubby使用Paxos算法[9,23]来保证其副本在失败时保持一致。Chubby提供了一个由目录和小文件组成的命名空间。每个目录或文件都可以用作锁,对文件的读写是原子的。Chubby客户端库提供了Chubby文件的一致缓存。每个Chubby客户端都使用Chubby服务维护会话。如果客户端会话无法在租约到期时间内续订其会话租约,则会话过期。当客户端的会话到期时,它会丢失所有的锁和打开的句柄。Chubby客户端还可以在Chubby文件和目录上注册回调,以通知更改或会话到期。
Bigtable在各种任务中使用Chubby:确保任何时候最多只有一个活跃的主服务器; 存储Bigtable数据的引导位置(参见5.1节); 发现片服务器并最终确定片服务器死亡(参见第5.2节); 存储Bigtable元信息(每个表的列族信息); 并存储访问控制列表。如果Chubby长时间不可用,Bigtable将无法使用。我们最近在跨越11个Chubby实例的14个Bigtable集群中测试了这种影响。由于Chubby不可用(由Chubby停机或网络问题引起)导致Bigtable中存储的某些数据无法使用的Bigtable服务小时数的平均百分比为0.0047%。受Chubby不可用性影响最大的单个集群的百分比为0.0326%。
5. 实现
Bigtable实现有三个主要组成:链接到每个客户端的库,一个主服务器和许多片服务器。可以从集群中动态添加(或删除)片服务器,以适应工作负载的变化。
主服务器负责将分片分配给片服务器,检测片服务器的添加和过期、均衡片服务器负载以及GFS中文件的垃圾收集。此外,它还处理模式更改,例如表和列族创建。
每个片服务器管理一组分片(通常我们每个片服务器有10到1000个分片)。片服务器处理对已加载的分片的读写请求,并且还会拆分已经过大的分片。与许多单主分布式存储系统[17,21]一样,客户端数据不会通过主服务器传输:客户端直接与片服务器通信以进行读写。由于Bigtable客户端不依赖主服务器来获取分片位置信息,因此大多数客户端从不与主服务器通信。因此,主服务器的负载实际很轻量。
Bigtable集群存储了许多表。每个表包含一组分片,每个分片包含与行范围相关的所有数据。最初,每个表只包含一个分片。随着表的增长,它会自动拆分为多个分片,默认情况下每个大小约为100-200 MB。
5.1 分片位置
我们使用类似于B+ tree [10]的三级层次结构来存储分片位置信息(图4)。
第一层是存储在Chubby中的文件,其中包含根分片的位置。根分片中的特殊METADATA表包含所有分片的位置。每个METADATA分片都包含一组用户分片的位置。根分片只是METADATA表中的第一个分片,但是经过特殊处理 - 它永远不会拆分 - 以确保分片位置层次结构不超过三个层级。
METADATA表将分片的位置存储在行键下,该行键是片的表标识符及其结束行的编码。每个METADATA行在内存中的存储大约为1KB的数据。由于适度的128 MB METADATA分片的限制,我们的三级定位方案足以定位2^34个分片(或128 MB分片中2^61字节)。
客户端库缓存分片位置。如果客户端不知道分片的位置,或者它发现缓存的位置信息不正确,则它会沿分片位置层次结构递归地向上移动。如果客户端的缓存为空,则位置算法需要三次网络往返,包括从Chubby读取一次。如果客户端的缓存是陈旧的,则位置算法可能需要六次往返,因为只有在未命中时才会发现过时的缓存条目(假设METADATA分片不会频繁移动)。由于分片位置存储在内存中,因此不需要访问GFS,但我们通过使用客户端库预拉取分片位置来进一步降低此成本:只要读取METADATA表,它就会读取多个分片的元数据。
我们还将辅助信息存储在METADATA表中,包括与每个分片相关的所有事件的日志(例如服务器开始提供服务时间)。此信息有助于调试和性能分析。
5.2 片分配
每个分片一次分配给一个片服务器。主服务器会跟踪活着的片服务器的集合,以及当前的分片到片服务器的分配,包括哪些分片未分配。如果分片未分配,并且一个片服务器具有足够的空间给该分片,则主服务器会通过向片服务器发送分片加载的请求来分配分片。
Bigtable使用Chubby来跟踪片服务器。当片服务器启动时,它会创建并获取对特定Chubby目录中唯一命名文件的独占锁。主服务器监控此目录(服务器目录)以发现片服务器。如果一个片服务器失去其独占锁,它将停止为其分片提供服务:例如,由于网络隔离导致服务器丢失其Chubby会话。(Chubby提供了一种有效的机制,允许片服务器检查它是否仍然保持锁而不会产生网络流量。)只要文件仍然存在,片服务器就会尝试重新获取其文件的独占锁。如果该文件不再存在,则片服务器将永远无法再次服务,因此它会自行终止。每当片服务器终止时(例如,因为集群管理系统正在从集群中移除片服务器的机器),它就会尝试释放其锁定,以便主服务器更快地重新分配其分片。
主服务器负责检测片服务器何时不再服务其分片,以及尽快重新分配这些分片。要检测片服务器何时不再为其分片提供服务,主服务器会定期向每个片服务器询问其锁状态。如果片服务器报告它已失去锁定,或者主服务器在最近几次尝试期间无法访问服务器,则主服务器会尝试获取该服务器文件的独占锁。如果主服务器能够获得锁,则Chubby处于活跃状态且片服务器已经死机或无法访问Chubby,因此主服务器确保片服务器永远不会通过删除其服务器文件再次服务。一旦服务器文件被删除后,主服务器可以将之前分配给该服务器的所有分片移动到未分配的分片集合中。为了确保Bigtable集群不容易受到主服务器和Chubby之间的网络问题的影响,如果其Chubby会话到期,主服务器将自行终止。但是,如上所述,主服务器故障不会改变分片到片服务器的分配。
当主服务器被集群管理系统启动时,它需要先获得当前的分片分配,然后才能更改它们。 主服务器在启动时执行以下步骤。(1) 主服务器在Chubby中获取一个唯一的主服务器锁,这会阻止并发的主服务器实例化。(2) 主服务器扫描Chubby中的服务器目录以查找活跃的服务器。(3) 主服务器与每个活跃片服务器通信,以发现已为每个服务器分配了哪些分片。(4) 主服务器扫描METADATA表以获知分片集合。每当此扫描遇到尚未分配的分片时,主服务器会将该分片添加到未分配分片的集合中,这使该分片有资格进行分片分配。
一个复杂的问题是,在分配METADATA分片之前,不能对METADATA表进行扫描。因此,在开始此扫描(步骤4)之前,如果在步骤3中未发现根分片的分配,则主服务器会将根分片添加到未分配的分片集合中。此添加确保将分配根分片。由于根分片包含所有METADATA分片的名称,因此主服务器在扫描根分片后会知道所有分片。
表的现有分片的集合只有在创建或删除表、将两个现有分片合并为一个更大的分片、或者将现有分片拆分为两个较小的分片时才会更改。主服务器能够跟踪这些变化,因为它会启动除最后一项之外的所有变化。分片拆分是特殊处理的,因为它们是由片服务器启动的。片服务器通过在METADATA表中记录新分片的信息来提交拆分。拆分提交后,它会通知主服务器。如果拆分通知丢失(由于片服务器或主服务器已经死亡),主服务器会在请求片服务器加载现在已拆分的分片时检测新分片。片服务器将通知主服务器该拆分,因为它在METADATA表中找到的分片条目将仅指定主机要求加载的一部分分片。
5.3 片服务器
分片的持久状态存储在GFS中,如图5所示。更新被提交到存储重做记录的提交日志中。在这些更新中,最近提交的更新存储在称为memtable的排序缓冲区的内存中; 较旧的更新存储在一系列SSTable中。要恢复分片,片服务器会从METADATA表中读取其元数据。此元数据包含组成分片的SSTable列表和一组重做点,这些重做点是指向可能包含分片数据的任何提交日志的指针。服务器将SSTable的索引读入内存,并通过应用自重做点以来已提交的所有更新来重构memtable。
当写操作到达片服务器时,服务器检查它是否格式正确,并且发送者是否有权执行变更。通过从Chubby文件中读取允许的写入器列表来执行授权(这几乎总是命中Chubby客户端缓存)。将有效的变更写入提交日志。分组提交用于提高许多小变更的吞吐量[13,16]。写入提交后,其内容将插入到memtable中。
当读取操作到达片服务器时,类似地会检查其是否格式良好并有适当的授权。在SSTables的列表和memtable的合并视图上执行有效的读操作。由于SSTable和memtable是按字典序排序的数据结构,因此可以有效地形成合并视图。
在拆分和合并分片的同时,可以继续进行读取和写入操作。
5.4 压缩
当写操作执行时,memtable的大小增加。当memtable大小达到阈值时,memtable被冻结,并创建一个新的memtable,冻结的memtable转换为SSTable并写入GFS。这个minor压缩过程有两个目标:它缩小了片服务器的内存使用量,并减少了如果此服务器死机时恢复期间必须从提交日志中读取的数据量。压缩发生时,输入的读写操作可以继续。
每次minor压缩都会创建一个新的SSTable。如果此行为继续未被遏制,则读取操作可能需要合并来自任意数量的SSTable的更新。反之,我们通过在后台定期执行合并压缩来限制此类文件的数量。合并压缩读取一些SSTable和memtable的内容,并写出一个新的SSTable。压缩完成后,可以丢弃输入的SSTable和memtable。
将所有SSTable重写为一个SSTable的合并压缩称为major压缩。非major压缩生成的SSTable可以包含特殊删除条目,这些条目可以抑制仍处于活跃状态的旧SSTable中的已删除数据。另一方面,major压缩产生不包含删除信息或删除数据的SSTable。Bigtable在其所有分片中循环、并定期对其进行major压缩。这些major压缩允许Bigtable回收已删除数据使用的资源,并允许它确保已删除的数据及时从系统中消失,这对于存储敏感数据的服务非常重要。
6. 改进
上一节中描述的实现需要进行一些改进,以实现用户所需的高性能、可用性和可靠性。本节更详细地描述了部分实现,以突出显示这些改进。
6.1 位置分组
客户端可以将多个列族组合到一个位置分组中。为每个分片中的每个位置分组生成单独的SSTable。将通常不一起访问的列族隔离到不同的位置分组中可以实现更高效的读取。例如,Webtable中的页面元数据(例如语言和校验和)可以位于一个位置分组中,并且页面的内容可以位于不同的分组中:想要读取元数据的应用不需要读取所有页面内容。
此外,可以基于每个位置分组指定一些有用的调整参数。例如,可以将位置分组声明到内存中。内存中位置分组的SSTable可以延迟加载到片服务器的内存中。一旦加载后,可以在不访问磁盘的情况下读取属于此位置分组的列族。此功能对于经常访问的小块数据非常有用:我们在内部将它用于METADATA表中的位置列族。
6.2 压缩
客户端可以控制SSTable是否压缩一个位置分组,以及如果是,则使用哪种压缩格式。用户指定的压缩格式应用于每个SSTable块(其大小可通过位置分组的特定调整参数控制)。虽然我们通过单独压缩每个块而损失了一些空间,但我们受益于可以在不解压缩整个文件的情况下读取SSTable的一小部分。许多客户端使用两遍自定义压缩方案。 第一遍使用Bentley和McIlroy的方案[6],它在大窗口中压缩长公共字符串。 第二遍使用快速压缩算法,该算法在数据的小16 KB窗口中查找重复项。两种压缩算法都非常快 - 它们以100-200 MB/s的速度编码,在现代机器上以400-1000 MB/s的速度进行解码。
尽管我们在选择压缩算法时强调速度而不是空间缩减,但这种两遍压缩方案确实出奇的好。例如,在Webtable中,我们使用此压缩方案来存储网页内容。在一个实验中,我们将大量文档存储在压缩的位置分组中。出于实验目的,我们限定每个文档只有一个版本,而不是存储对我们可用的所有版本。该方案实现了空间减少到10:1。这比基于HTML页面典型的Gzip压缩减少到3:1或4:1要好得多,因为Webtable行的布局方式:来自同一个主机的所有页面都彼此靠近存储。这允许Bentley-McIlroy算法识别来自同一主机的页面中的大量共享引用。许多应用(不仅仅是Webtable)选择其行名称,以便类似的数据最终聚集在一起,从而实现非常好的压缩率。当我们在Bigtable中存储相同值的多个版本时,压缩率会更好。
6.3 为读取性能缓存
为了提高读取性能,片服务器使用两级缓存。扫描缓存是一种更高级别的缓存,用于将SSTable接口返回的键值对缓存到片服务器代码中。块缓存是一个较低级别的缓存,用于缓存从GFS读取的SSTables块。扫描缓存对于倾向于重复读取相同数据的应用最有用。块缓存对于倾向于读取与其最近读取的数据接近的数据的应用(例如,顺序读取,或热行内相同位置分组中的不同列的随机读取)非常有用。
6.4 布隆过滤器
如第5.3节所述,读取操作必须从组成分片状态的所有SSTable中读取。如果这些SSTable不在内存中,我们最终可能会进行许多磁盘访问。我们通过允许客户端指定应该为特定位置分组中的SSTable创建的Bloom过滤器[7]来减少访问次数。Bloom过滤器允许我们询问SSTable是否可能包含指定行/列对的任何数据。对于某些应用,用于存储Bloom过滤器的少量片服务器内存大大减少了读取操作所需的磁盘搜索次数。我们对Bloom过滤器的使用也意味着对不存在的行或列的大多数查找不需要接触磁盘。
6.5 提交日志实现
如果我们将每个分片的提交日志保存在单独的日志文件中,则会在GFS中同时写入大量文件。依赖于每个GFS服务器上的基础文件系统实现,这些写入可能导致大量磁盘搜索以写入不同的物理日志文件。此外,每个分片具有单独的日志文件也会降低分组提交优化的效果,因为分组往往会更小。为了解决这些问题,我们将变更添加到每个片服务器的单个提交日志中,在同一物理日志文件[18,20]中混合不同分片的变更。
在正常操作中使用单一日志可提供显著的性能优势,但这会使恢复变得复杂。当片服务器死机时,它所服务的分片将被移动到许多其他片服务器:每台服务器通常会加载少量原服务器的分片。要恢复分片的状态,新的片服务器需要从原片服务器写入的提交日志中重新应用该分片的变更。但是,这些分片的变更混合在同一物理日志文件中。一种方法是每个新的片服务器读取这个完整的提交日志文件,并仅应用它需要恢复的分片所需的条目。但是,在这样的方案下,如果从故障片服务器给100台计算机的每台计算机分配一个分片,那么日志文件将被读取100次(每个服务器一次)。
我们通过首先按照键的顺序对提交日志条目进行排序来避免重复日志读取。在排序的输出中,特定分片的所有变更都是连续的,因此可以通过一次磁盘搜索然后顺序读取来高效读取。为了并行化排序,我们将日志文件分区为64 MB段,并在不同的片服务器上并行对每个段进行排序。此排序过程由主服务器协调,并在片服务器表示需要从某个提交日志文件中恢复变更时启动。
将提交日志写入GFS有时会由于各种原因导致性能问题(例如,GFS服务器计算机涉及写入崩溃中,或者到达特定的三个GFS服务器集合的网络路径正在遭受网络拥塞,或者负载过重)。为了保护GFS延迟峰值变更,每个片服务器实际上有两个日志写入线程,每个线程写入自己的日志文件; 这两个线程同时只有一个在活跃使用中。如果对活跃日志文件的写入性能不佳,则将日志文件写入切换到另一个线程,并且提交日志队列中的变更由新激活的日志写入线程写入。日志条目包含序列号,以允许恢复过程忽略由此日志切换过程产生的重复条目。
6.6 加快分片的恢复速度
如果主服务器将分片从一台片服务器移动到另一台,则源片服务器首先会对该分片进行minor压缩。该压缩减少了片服务器的提交日志中未压缩状态的数量来缩短恢复时间。完成此压缩后,片服务器将停止为该分片提供服务。在实际卸载分片之前,片服务器会执行另一次(通常是非常快速的)minor压缩,以消除在执行第一次minor压缩时到达的片服务器日志中的任何剩余未压缩状态。在完成第二次minor压缩之后,可以将该分片加载到另一台片服务器上,而无需任何日志条目的恢复。
6.7 利用不变性
除了SSTable缓存之外,Bigtable系统的其他各个部分都被简化了,因为我们生成的所有SSTable都是不可变的。例如,从SSTables读取时,我们不需要对访问文件系统同步。因此,可以非常有效地实现对行的并发控制。读取和写入都可访问的唯一可变数据结构是memtable。为了减少读取memtable期间的竞争,我们将memtable的每个行写入进行写时复制并允许读取和写入并行进行。
由于SSTables是不可变的,因此永久删除已删除数据的问题将转换为垃圾收集过时的SSTables。每个分片的SSTable都在METADATA表中注册。主服务器将过时的SSTable利用标记清除垃圾收集[25]从SSTable集合移除,其中METADATA表包含根集合。
最后,SSTables的不变性使我们能够快速拆分分片。我们让子分片共享父分片的SSTables,而不是为每个子分片生成一组新的SSTable。
7. 性能评估
我们搭建了一个带有N台片服务器的Bigtable集群,用于测量Bigtable的性能和可扩展性,因为N是多变的。片服务器配置为使用1 GB内存并写入由1786台机器组成的GFS单元,每台机器具有两个400 GB IDE硬盘驱动。N台客户机生成了用于这些测试的Bigtable负载。(我们使用与片服务器相同数量的客户端来确保客户端永远不会成为瓶颈。)每台机器都有两个双核Opteron 2 GHz芯片,足够的物理内存来容纳所有正在运行的进程的工作集,以及一个千兆比特以太网链路。这些机器被安排在一个两级树形交换网络中,根部有大约100-200 Gbps的总带宽。所有机器都在同一个托管设施中,因此任何两台机器之间的往返时间不到一毫秒。
片服务器和主服务器,测试客户端和GFS服务器都运行在同一组计算机上。每台机器都运行一个GFS服务器。某些计算机还运行片服务器或客户端进程,或者与这些实验同时使用资源池的其他作业的进程。
R是测试中涉及的Bigtable不同行键的数量。选择R以使每个基准测试从每个片服务器读取或写入大约1 GB的数据。
顺序写入基准测试使用名称为0到R-1的行键。行键的这个空间被划分为10N个相等大小的范围。这些范围由中央调度程序分配给N个客户端,一旦客户端处理完成分配给它的前一个范围,就将下一个可用范围分配给该客户端。此动态分配有助于减轻由客户端计算机上运行的其他进程引起的性能变化的影响。我们在每个行键下面写了单个字符串。每个字符串都是随机生成的,因此是不可压缩的。另外,不同行键下的字符串是不同的,因此不可能进行跨行压缩。随机写入基准测试是类似的,除了在写入之前立即对行键进行模数R散列,以便在整个基准测试持续时间内将写入负载大致均匀地分布在整个行空间中。
顺序读取基准测试以与顺序写入基准测试完全相同的方式生成行键,但不是在行键下写入,而是读取存储在行键下的字符串(由早期的顺序写入基准测试调用写入)。类似地,随机读取基准测试隐藏了随机写入基准测试的操作。
扫描基准测试与顺序读取基准测试类似,但使用Bigtable API提供的支持以扫描行范围内的所有值。由于单个RPC从片服务器获取大量值,因此使用扫描可减少基准测试执行的RPC数量。随机读取(mem)基准测试类似于随机读取基准测试,但包含有基准测试数据的位置分组被标记在内存中,因此从片服务器的内存中读取数据,而不是需要GFS读取。对于此基准测试,我们将每台片服务器的数据量从1 GB减少到100 MB,以便它可以轻松被放入片服务器可用的内存中。
图6显示了在向Bigtable读取和写入1000字节值时基准测试性能的两个视图。该表显示了每台片服务器每秒的操作数; 该图显示了每秒的总操作数。
7.1 单个片服务器性能
让我们首先考虑一台片服务器的性能。随机读取比所有其他操作慢一个数量级或更多。每次随机读取都涉及通过网络将64 KB SSTable块从GFS传输到片服务器,其中只使用了1000字节的值。片服务器每秒执行大约1200次读取,这转换为从GFS大约75 MB/s的数据读取。由于我们的网络堆栈、SSTable解析和Bigtable代码的开销,这个带宽足以使片服务器CPU饱和,并且几乎足以使我们系统中使用的网络链路饱和。具有此类访问模式的大多数Bigtable应用将块大小减小到较小的值,通常为8KB。
从内存中随机读取要快得多,因为每1000字节的读取从片服务器的本地内存中读取而不从GFS获取大的64 KB块。
随机和顺序写入比随机读取执行得更好,因为每个片服务器将所有输入的写入附加到单个提交日志中,并使用分组提交将这些写入有效地流式传输到GFS。随机写入和顺序写入的性能没有显著差异; 在这两种情况下,对片服务器的所有写入都记录在同一个提交日志中。
顺序读取比随机读取执行得更好,因为从GFS获取的每个64 KB SSTable块都存储在我们的块缓存中,用于为接下来的64个读取请求提供服务。
由于片服务器可以返回大量值以响应单个客户端RPC,因此扫描速度更快,因此RPC开销会在大量值上分摊。
7.2 扩展性
随着我们将系统中的片服务器数量从1增加到500,总体吞吐量急剧增加了一百倍。例如,当片服务器增加500倍,内存中随机读取的性能增加了近300倍。出现这种情况是因为此基准测试的性能瓶颈是单个片服务器CPU。
但是,性能没有线性增加。对于大多数基准测试,从1台到50台片服务器时,每台服务器吞吐量显著下降。这种下降是由多个服务器配置中的负载不平衡引起的,通常是由于其他进程争用CPU和网络。我们的负载均衡算法试图解决这种不平衡问题,但由于两个主要原因无法完成工作:重新均衡会受限于减少分片的移动次数(分片短时间内不可用,当移动它时通常不到一秒钟),随着基准测试的前进,我们的基准测试产生的负载会随之偏移。
随机读取基准测试显示了最差的扩展(服务器数量增加了500倍,总吞吐量增加了100倍)。出现此问题的原因是(如上所述)我们通过网络为每1000字节读取传输一个大的64KB块。这种传输使我们网络中各个共享的1千兆比特链路达到饱和,因此,随着我们增加机器数量,每台服务器吞吐量显著下降。
8. 实际应用
截至2006年8月,共有388个非测试Bigtable集群在各Google机器集群中运行,总计约24500台片服务器。表1显示了每个集群的片服务器的粗略分布。许多这些集群用于开发目的,因此在很长一段时间内处于闲置状态。一组14个繁忙的集群,总计8069个片服务器,每秒的请求总量超过120万,输入的RPC流量约为741 MB/s,输出的RPC流量约为16 GB/s。
表2提供了有关当前使用的一些表的一些数据。有些表存储提供给用户服务的数据,而有些表存储用于批处理的数据; 这些表在包括总大小、平均单元大小、从内存提供的数据百分比以及表模式的复杂性方面范围很广。在本节的其余部分,我们将简要介绍三个产品团队如何使用Bigtable。
8.1 Google Analytics
Google Analytics(analytics.google.com)是一项服务,可帮助网站管理员分析其网站上的流量模式。它提供了汇总统计信息,例如每天唯一身份访问者的数量和每个URL每天的网页浏览量,以及网站跟踪报告,例如进行购买的用户百分比,因为他们之前查看过特定网页。
为了启用该服务,网站管理员在其网页中嵌入了一个小型JavaScript程序。每当访问页面时都会调用此程序。它会在Google Analytics中记录有关请求的各种信息,例如用户标识符和有关正在获取的页面的信息。Google Analytics汇总了这些数据,并将其提供给网站管理员。
我们简要介绍Google Analytics使用的两个表。原始点击表(~200 TB)为每个终端用户会话维护一行。行名称是一个元组,包含网站的名称和创建会话的时间。此模式可确保访问同一网站的会话是连续的,并且它们按时间顺序排序。此表压缩到原始大小的14%。
摘要表(~20 TB)包含每个网站的各种预定义摘要。此表是通过定期调度的MapReduce作业从原始点击表生成的。每个MapReduce作业都从原始点击表中提取最近的会话数据。整个系统的吞吐量受到GFS吞吐量的限制。此表压缩到原始大小的29%。
8.2 Google Earth
Google通过基于网络的Google地图界面(maps.google.com)和Google Earth(earth.google.com)顾客客户端软件运营一系列服务,为用户提供访问世界范围地面的高分辨率卫星图像的权限。这些产品允许用户在世界各地进行导航:他们可以在许多不同级别的分辨率下平移、查看和标注卫星图像。该系统使用一个表来预处理数据,使用一组不同的表来提供客户端数据。
预处理管道使用一个表来存储原始图像。在预处理期间,图像被清理并合并到最终的服务数据中。该表包含大约70 TB的数据,因此从磁盘提供服务。图像已经被有效压缩,因此禁用Bigtable压缩。
图像表中的每一行对应一个地理段。命名行以确保相邻的地理段彼此靠近存储。该表包含一个列族,用于跟踪每个段的数据源。此列族具有大量列:基本上每个原始数据一列。由于每个段仅由几个图像构成,因此该列族非常稀疏。
预处理管道在很大程度上依赖于Bigtable上的MapReduce来转换数据。在某些MapReduce作业期间,整个系统的每个片服务器处理超过1 MB/s的数据。
服务系统使用一个表来索引存储在GFS中的数据。此表相对较小(~500 GB),但每个数据中心每秒必须提供数万个低延迟的查询。因此,该表托管在数百台片服务器上,并在内存中容纳列族。
8.3 Personalized Search
Personalized Search(www.google.com/psearch)是一项选择性服务,可记录用户在各种Google业务上的查询和点击,例如网络搜索、图片和新闻。用户可以浏览他们的搜索历史记录以重新访问他们的旧查询和点击,他们可以根据他们历史的Google使用模式请求个性化搜索结果。
Personalized Search将每个用户的数据存储在Bigtable中。每个用户都有一个唯一的userid,并被分配一个由该userid命名的行。所有用户操作都存储在表中。为每种类型的操作保留单独的列族(例如,存在存储所有Web查询的列族)。每个数据元素使用Bigtable时间戳作为对应用户操作发生的时间。Personalized Search使用Bigtable上的MapReduce生成用户画像。这些用户画像用于个性化实时搜索结果。
Personalized Search数据在多个Bigtable集群中进行复制,以提高可用性并减少因与客户端的距离而导致的延迟。Personalized Search团队最初在Bigtable之上构建了一个客户端复制机制,并确保了所有副本的最终一致性。当前系统现在使用内置于服务器中的复制子系统。
Personalized Search存储系统的设计允许其他团队在其自己的列中添加新的每个用户的信息,并且该系统现在被许多其他需要存储每个用户的配置选项和设置的Google业务使用。在许多团队之间共享一个表导致了非常多的列族。为了帮助支持共享,我们为Bigtable添加了一个简单的配额机制,以限制共享表中任何特定客户端的存储消耗; 此机制在使用此系统的各个产品团队之间为每个用户的信息存储提供了一些隔离。
9. 教训
在设计、实施、维护和支持Bigtable的过程中,我们获得了有用的经验,并学到了几个有趣的教训。
我们学到的一个教训是,大型分布式系统容易受到许多类型的故障的影响,而不仅仅是许多分布式协议中假设的标准网络分区和失败停止故障。例如,我们看到了由于以下所有原因导致的问题:内存和网络损坏、大的时钟偏差、挂机、扩展和非对称网络分区、我们正在使用的其他系统中的错误(例如Chubby)、GFS配额溢出、计划内和计划外硬件维护。由于我们已经获得了更多这些问题的经验,我们通过改变各种协议来解决它们。例如,我们将校验和添加到RPC机制中。我们还通过去除系统的一部分关于另一部分的假设来处理一些问题。例如,我们停止假设给定的Chubby操作只能返回一组固定的错误。
我们学到的另一个教训是,在明确如何使用新功能之前,延迟添加新功能非常重要。例如,我们最初计划在API中支持通用事务。但是,由于我们没有立即使用它们,因此我们没有实现它们。既然我们在Bigtable上运行了许多真正的应用,我们就能够检验它们的实际需求,并发现大多数应用只需要单行事务。在人们要求分布式事务的地方,最重要的用途是维护二级索引,我们计划增加一种专门的机制来满足这种需求。新机制不如分布式事务通用,但效率更高(特别是对于跨越数百行或更多行的更新),并且还可以更好地与我们的乐观的跨数据中心复制方案进行交互。
我们从支持Bigtable中学到的实用的经验教训是适当的系统级监控的重要性(即监控Bigtable本身以及使用Bigtable的客户端进程)。例如,我们扩展了我们的RPC系统,以便对于RPC的样本,它保留了代表该RPC重要操作完成的详细跟踪。此功能使我们能够检测并修复许多问题,例如分片数据结构上的锁竞争、提交Bigtable变更时写入GFS的速度慢、以及当METADATA分片不可用时对METADATA表的访问卡顿。另一个有用的监控示例是每个Bigtable集群都在Chubby中注册。这使我们能够追踪所有集群、发现它们有多大、查看它们运行的软件版本、接收的流量、以及是否存在任何问题,例如意外的大延迟。
我们学到的最重要的教训是简单设计的价值。鉴于我们系统的大小(大约100000行非测试代码),以及代码以意想不到的方式随时间演变的事实,我们发现代码和设计的清晰度对代码维护和调试有很大帮助。其中一个例子是我们的片服务器成员协议。我们的第一个协议很简单:主服务器定期向片服务器发放租约,如果租约到期,片服务器会自行终止。遗憾的是,该协议在存在网络问题时显著降低了可用性,并且对主服务器恢复时间也很敏感。我们重新设计了协议几次,直到我们有一个表现良好的协议。但是,生成的协议过于复杂,并且依赖于其他应用很少使用的Chubby功能的行为。我们发现,我们花费了大量时间来调试模糊的角落情况,不仅在Bigtable代码中,而且在Chubby代码中。最终,我们取消了这个协议并转而采用了一种更简单的新协议,该协议完全取决于广泛使用的Chubby功能。
10. 相关工作
Boxwood项目[24]的组件在某些方面与Chubby、GFS和Bigtable重叠,因为它提供分布式协议、锁、分布式块存储和分布式B树存储。在存在重叠的每种情况下,看起来Boxwood的组件的目标水平低于相应的Google服务。Boxwood项目的目标是为构建更高级别的服务(如文件系统或数据库)提供基础设施,而Bigtable的目标是直接支持希望存储数据的客户端应用。
许多最近的项目已经解决了通过广域网(通常是“互联网规模”)提供分布式存储或更高级别服务的问题。这包括以CAN[29]、Chord[32]、Tapestry[37]和Pastry[30]等项目开始的分布式哈希表的工作。这些系统解决了Bigtable不会出现的问题,例如高度可变的带宽、不可信的参与者或频繁的重新配置; 分散控制和拜占庭容错并不是Bigtable的目标。
就应用开发者可能提供的分布式数据存储模型而言,我们认为分布式B树或分布式哈希表提供的键值对模型过于局限。键值对是一个有用的构建块,但它们不应该是为开发者提供的唯一构建块。我们选择的模型比简单的键值对更丰富,并支持稀疏的半结构化数据。尽管如此,它仍然很简单,它是一个非常有效的平面文件表示,并且它足够透明(通过位置分组),以允许我们的用户调整系统的重要行为。
一些数据库供应商开发了可以存储大量数据的并行数据库。Oracle的Real Application Cluster数据库[27]使用共享磁盘来存储数据(Bigtable使用GFS)和分布式锁管理器(Bigtable使用Chubby)。IBM的DB2 Parallel Edition[4]基于类似于Bigtable的非共享[33]架构。每个DB2服务器负责存储在本地关系数据库中表的行的子集。这两种产品对其完整的关系模型都提供了事务。
Bigtable位置分组实现了类似的压缩和磁盘读取性能优势,这些优势来自于其他在磁盘上使用基于列的存储而不是基于行的存储组织数据的系统(包括C-Store[1,34]和商业产品,如Sybase IQ[15, 36]、SenSage[31]、KDB +[22]和MonetDB/X100中的ColumnBM存储层[38])。另一个将垂直和水平数据分成平面文件并实现良好数据压缩率的系统是AT&T的Daytona数据库[19]。位置分组不支持CPU缓存级优化,例如Ailamaki[2]所描述的优化。
Bigtable使用memtables和SSTables将更新存储到分片的方式类似于Log-Structured Merge Tree[26]存储对索引数据的更新的方式。在两个系统中,排序数据在写入磁盘之前都在内存中缓存,读取必须合并内存和磁盘中的数据。
C-Store和Bigtable共享许多特性:两个系统都使用非共享体系结构,并且具有两种不同的数据结构,一种用于最近的写入,另一种用于存储长期存在的数据,具有将数据从一种形式移动到另一种形式的机制。这些系统的API差别很大:C-Store的行为类似于关系数据库,而Bigtable提供较低级别的读写接口,旨在支持每台服务器每秒数千次此类操作。C-Store也是“读取优化的关系型DBMS”,而Bigtable在读取密集型和写入密集型应用上都提供了良好的性能。
Bigtable的负载均衡器必须解决非共享数据库所面临的一些相同类型的负载和内存平衡问题(例如,[11,35])。我们的问题稍微简单一点:(1) 我们不考虑相同数据(可能是由于视图或索引的替代形式)的多个副本的可能性; (2) 我们让用户告诉我们哪些数据属于内存,哪些数据应保留在磁盘上,而不是试图动态确定; (3) 我们没有复杂的查询来执行或优化。
11. 总结
我们已经描述了Bigtable,一种在Google中用于存储结构化数据的分布式系统。Bigtable集群自2005年4月开始投入生产使用,在此之前我们在设计和实施上花费了大约7个人年。截至2006年8月,超过60个项目正在使用Bigtable。我们的用户喜欢Bigtable实现提供的性能和高可用性,并且他们可以通过在系统资源需求随时间变化时向系统添加更多计算机来扩展其集群的容量。
鉴于Bigtable的不寻常的接口,一个有趣的问题是我们的用户适应使用它有多困难。新用户有时不确定如何最好地使用Bigtable接口,特别是如果他们习惯于使用支持通用事务的关系数据库。尽管如此,许多Google产品成功使用Bigtable的事实表明我们的设计在实践中运作良好。
我们正在实现其他几个Bigtable功能,例如支持二级索引和构建跨数据中心复制的多主服务器副本的Bigtables的基础设施。我们还开始将Bigtable作为服务部署到产品团队,以便各个团队不需要维护自己的集群。随着我们服务集群的扩展,我们需要在Bigtable内部处理更多的资源共享问题[3,5]。
最后,我们发现在Google内构建自己的存储解决方案有很大的优势。通过为Bigtable设计我们自己的数据模型,我们获得了很大的灵活性。此外,我们对Bigtable的实现以及Bigtable所依赖的其他Google基础设施的控制意味着我们可以消除他们出现的瓶颈和低效率。
致谢
我们感谢匿名审稿人David Nagle和我们的上级Brad Calder对本文的反馈。Bigtable系统受益于Google内众多用户的反馈。此外,我们感谢以下人士对Bigtable的贡献:Dan Aguayo,Sameer Ajmani,Zhifeng Chen,Bill Coughran,Mike Epstein,Healfdene Goguen,Robert Griesemer,Jeremy Hylton,Josh Hyman,Alex Khesin,Joanna Kulik,Alberto Lerner, Sherry Listgarten,Mike Maloney,Eduardo Pinheiro,Kathy Polizzi,Frank Yellin和Arthur Zwiegincew。
参考文献
ABADI, D. J., MADDEN, S. R., AND FERREIRA, M. C. Integrating compression and execution in columnoriented database systems. Proc. of SIGMOD (2006).
AILAMAKI, A., DEWITT, D. J., HILL, M. D., AND SKOUNAKIS, M. Weaving relations for cache performance. In The VLDB Journal (2001), pp. 169-180.
BANGA, G., DRUSCHEL, P., AND MOGUL, J. C. Resource containers: A new facility for resource management in server systems. In Proc. of the 3rd OSDI (Feb. 1999), pp. 45-58.
BARU, C. K., FECTEAU, G., GOYAL, A., HSIAO, H., JHINGRAN, A., PADMANABHAN, S., COPELAND, G. P., AND WILSON, W. G. DB2 parallel edition. IBM Systems Journal 34, 2 (1995), 292-322.
BAVIER, A., BOWMAN, M., CHUN, B., CULLER, D., KARLIN, S., PETERSON, L., ROSCOE, T., SPALINK, T., AND WAWRZONIAK, M. Operating system support for planetary-scale network services. In Proc. of the 1st NSDI (Mar. 2004), pp. 253-266.
BENTLEY, J. L., AND MCILROY, M. D. Data compression using long common strings. In Data Compression Conference (1999), pp. 287-295.
BLOOM, B. H. Space/time trade-offs in hash coding with allowable errors. CACM 13, 7 (1970), 422-426.
BURROWS, M. The Chubby lock service for looselycoupled distributed systems. In Proc. of the 7th OSDI (Nov. 2006).
CHANDRA, T., GRIESEMER, R., AND REDSTONE, J. Paxos made live —— An engineering perspective. In Proc. of PODC (2007).
COMER, D. Ubiquitous B-tree. Computing Surveys 11, 2 (June 1979), 121-137.
COPELAND, G. P., ALEXANDER, W., BOUGHTER, E. E., AND KELLER, T. W. Data placement in Bubba. In Proc. of SIGMOD (1988), pp. 99-108.
DEAN, J., AND GHEMAWAT, S. MapReduce: Simplified data processing on large clusters. In Proc. of the 6th OSDI (Dec. 2004), pp. 137-150.
DEWITT, D., KATZ, R., OLKEN, F., SHAPIRO, L., STONEBRAKER, M., AND WOOD, D. Implementation techniques for main memory database systems. In Proc. of SIGMOD (June 1984), pp. 1-8.
DEWITT, D. J., AND GRAY, J. Parallel database systems: The future of high performance database systems. CACM 35, 6 (June 1992), 85-98.
FRENCH, C. D. One size fits all database architectures do not work for DSS. In Proc. of SIGMOD (May 1995), pp. 449-450.
GAWLICK, D., AND KINKADE, D. Varieties of concurrency control in IMS/VS fast path. Database engineering Bulletin 8, 2 (1985), 3-10.
GHEMAWAT, S., GOBIOFF, H., AND LEUNG, S.-T. The Google file system. In Proc. of the 19th ACM SOSP (Dec. 2003), pp. 29-43.
GRAY, J. Notes on database operating systems. In Operating Systems —— An Advanced Course, vol. 60 of Lecture Notes in Computer Science. Springer-Verlag, 1978.
GREER, R. Daytona and the fourth-generation language Cymbal. In Proc. of SIGMOD (1999), pp. 525-526.
HAGMANN, R. Reimplementing the Cedar file system using logging and group commit. In Proc. of the 11th SOSP (Dec. 1987), pp. 155-162.
HARTMAN, J. H., AND OUSTERHOUT, J. K. The Zebra striped network file system. In Proc. of the 14th SOSP (Asheville, NC, 1993), pp. 29-43.
KX.COM. kx.com/products/database.php. Product page.
LAMPORT, L. The part-time parliament. ACM TOCS 16, 2 (1998), 133-169.
MACCORMICK, J., MURPHY, N., NAJORK, M., THEKKATH, C. A., AND ZHOU, L. Boxwood: Abstractions as the foundation for storage infrastructure. In Proc. of the 6th OSDI (Dec. 2004), pp. 105-120.
MCCARTHY, J. Recursive functions of symbolic expressions and their computation by machine. CACM 3, 4 (Apr. 1960), 184-195.
O’NEIL, P., CHENG, E., GAWLICK, D., AND O’NEIL, E. The log-structured merge-tree (LSM-tree). Acta Inf. 33, 4 (1996), 351-385.
ORACLE.COM. www.oracle.com/technology/products/-database/clustering/index.html. Product page.
PIKE, R., DORWARD, S., GRIESEMER, R., AND QUINLAN, S. Interpreting the data: Parallel analysis with Sawzall. Scientific Programming Journal 13, 4 (2005), 227-298.
RATNASAMY, S., FRANCIS, P., HANDLEY, M., KARP, R., AND SHENKER, S. A scalable content-addressable network. In Proc. of SIGCOMM (Aug. 2001), pp. 161-172.
ROWSTRON, A., AND DRUSCHEL, P. Pastry: Scalable, distributed object location and routing for largescale peer-to-peer systems. In Proc. of Middleware 2001 (Nov. 2001), pp. 329-350.
SENSAGE.COM. sensage.com/products-sensage.htm.Product page.
STOICA, I., MORRIS, R., KARGER, D., KAASHOEK, M. F., AND BALAKRISHNAN, H. Chord: A scalable peer-to-peer lookup service for Internet applications. In Proc. of SIGCOMM (Aug. 2001), pp. 149-160.
STONEBRAKER, M. The case for shared nothing. Database Engineering Bulletin 9, 1 (Mar. 1986), 4-9.
STONEBRAKER,M., ABADI, D. J., BATKIN, A., CHEN, X., CHERNIACK, M., FERREIRA, M., LAU, E., LIN, A., MADDEN, S., O’NEIL, E., O’NEIL, P., RASIN, A., TRAN, N., AND ZDONIK, S. C-Store: A columnoriented DBMS. In Proc. of VLDB (Aug. 2005), pp. 553-564.
STONEBRAKER, M., AOKI, P. M., DEVINE, R., LITWIN, W., AND OLSON, M. A. Mariposa: A new architecture for distributed data. In Proc. of the Tenth ICDE (1994), IEEE Computer Society, pp. 54-65.
SYBASE.COM. www.sybase.com/products/databaseservers/sybaseiq. Product page.
ZHAO, B. Y., KUBIATOWICZ, J., AND JOSEPH, A. D. Tapestry: An infrastructure for fault-tolerant wide-area location and routing. Tech. Rep. UCB/CSD-01-1141, CS Division, UC Berkeley, Apr. 2001.
ZUKOWSKI, M., BONCZ, P. A., NES, N., AND HEMAN, S. MonetDB/X100 —— A DBMS in the CPU cache. IEEE Data Eng. Bull. 28, 2 (2005), 17-22.
你可能感兴趣的:(读书笔记,bigtable,分布式存储,cluster,kv,database)
读书笔记《穿越寒冬》
如雪般飞舞
各位好,我们今天来讲一本书,名字叫作《穿越寒冬》。看起来特别应景,大家觉得现在创业的状况不景气,大家都在忍受着寒冬的煎熬。但实际上,这本书的英文名字并不是这个意思,它的英文名叫作“如何创立一家新公司,并且能够活下来”。我在整个读完了以后,我发现这本书真正要翻译得好,它的名字应该叫作《创业生存手册》。这个书的作者,来自硅谷的霍夫曼船长。霍夫曼船长写过一本让创业者觉得特别贴心的书,叫作《让大象飞》它和
设置mysql 数据库和表 的编码方式UTF-8
盖盖衍上
中间件 数据库 mysql oracle
要设置MySQL数据库表和字段的编码方式为UTF-8,可以使用下面的SQL语句:1.设置数据库默认编码为UTF-8:ALTERDATABASEyour_database_nameCHARACTERSETutf8mb4COLLATEutf8mb4_unicode_ci;2.创建表时指定编码为UTF-8:CREATETABLEyour_table_name(column1VARCHAR(100)CHA
kafka-eagle 配置文件修改使用自带的数据库
bright future cheer
kafka 数据库 分布式
######################################multizookeeper&kafkaclusterlistSettingsprefixedwith‘kafka.eagle.’willbedeprecated,use‘efak.’instead######################################efak.zk.cluster.alias=clu
读书笔记|《穆斯林的葬礼》
飞舞的微辰
她从来也没有打算对过去的恩怨进行报偿或是惩罚,只是想把该记住的都记住,该忘却的都忘却。事业的追求,并不一定要什么头衔和称号来满足,你爱上了一种东西,愿意用全部心血去研究它,掌握它,从中得到乐趣,并且永远也不舍得丢其它,这是事业心,是比什么都重要的......人生在世,谁也管不了谁;生儿育女,不是为了父母,是为了儿女自己,各人的路,让他们自己去闯吧。七尺之躯,一抔黄土,穆斯林们一个个都离去了,什么都
D43+1组棉布+《一个人的朝圣》读书笔记
棉布家的小橘子
前几天读了《一个人的朝圣》,感受到信念、目标对一个人是多么重要。哈罗德因为奎妮的一封告别信,步行横跨英格兰去探望她。因为有了目标和信念他才能坚持下去。而奎妮也一直在等他。一路哈罗德回忆儿子戴维,回忆自己小时候的遭遇,回忆与妻子莫琳的种种。想通了许多事情,与其说他要去拯救奎妮不如说在拯救自己。哈罗德与父母哈罗德的童年是不幸的,爸爸妈妈根本没有想当父母却生下了他。妈妈离家出走,爸爸开始找不同的阿姨,在
SQL运维_Unix下MySQL-8.0.18配置文件示例
Mostcow
SQL sql 运维 unix
SQL运维_Unix下MySQL-8.0.18配置文件示例MySQL是一个关系型数据库管理系统,由瑞典MySQLAB公司开发,属于Oracle旗下产品。MySQL是最流行的关系型数据库管理系统之一,在WEB应用方面,MySQL是最好的RDBMS(RelationalDatabaseManagementSystem,关系数据库管理系统)应用软件之一。MySQL是一种关系型数据库管理系统,关系数据库将
读书笔记-《如何抑制女性写作》-20210215
关七666
性别歧视和对性别的偏见,原来不仅仅是在中国,世界各地都需要改变。女性写作被认为是不正常的,没人看,或者否则其作者身份,认为是她们身边的男性写的,亦或者是它自行完成。为什么作者需要区分性别,是男性写的就是大作,是女性写的就是造作。这本书,揭示的是过去20世纪的女性作家们面对的种种非议。
Linux系统定时备份mysql数据库
er_得一
数据库 mysql oracle
1、创建shell脚本mysql_db_backup并赋予执行权限#!/bin/bash#备份目录BACKUP=/data/backup/db#当前时间DATETIME=$(date+%Y-%m-%d_%H%M%S)echo$DATETIME#数据库地址HOST=localhost#数据库用户名DB_USER=root#数据库密码DB_PW=pwd@123#备份的数据库名DATABASE=Apol
git切换分支时,如何保存当前分支的修改(暂时不想提交)
旅行者xy
有时候我们在一个分支中修改了部分文件,这时候,有个新的紧急任务,需要马上修改。一个好的想法是切换到一个新的分支,在新的分支上进行修改提交。可是这时候你使用gitcheckoutnew_branch时会提示错误信息:*error:Yourlocalchangestothefollowingfileswouldbeoverwrittenbycheckout:config/database.phpPle
mysqldump 参数说明
yjph83
mysql / mycat 数据库
参数说明--all-databases,-A导出全部数据库。mysqldump-uroot-p--all-databases--all-tablespaces,-Y导出全部表空间。mysqldump-uroot-p--all-databases--all-tablespaces--no-tablespaces,-y不导出任何表空间信息。mysqldump-uroot-p--all-database
《短篇小说写作指南》之读书笔记十九
平原雪
【弗雷德·格罗夫《用场景来检验你的故事》】阅读笔记一、阅读摘抄1.场景的好处:(1)它会赋予你的小说结构和连续性,可以处理章节之间的断裂。(2)它会推进角色和情节,并且场景间的转换体现了时间的流动,使得角色的变化因为有时间作为参照而更加可信。2.用戏剧性的场景来检验你的故事是非常可靠的一个办法。比如,故事的情节陷入停滞,也许场景能帮助你发现哪里出了问题。(1)也许是情节太顺利,没有足够的阻力。(2
D58+5组菜菜《高效人士用超级笔记术》读书笔记
爱分享的Amy菜菜
今天将整合笔记和创意笔记的部分,在手机微信读书看完了,蛮多阅读笔记类书籍方法都会有类似的地方,整合笔记里的○,箭头符号,还有VS,?,☆,对话框,完全可以规划做笔记的方法,自己平时只会用☆代表重要,现在在做笔记方法又多了几个纪录方式,关于电子笔记检索,很实用是里面通过关键词来学习的方法的方式,做笔记形式越简单越好。关于创意笔记里的纪录方式也很是实用,特别是handle化,这个真的......吗?我
《怎样成为一名优秀英语教师》读书笔记5
芳草June
(文刘俊芳)第五章《理解英语学习》主要内容梳理如下:1.作为英语教师要重视培养文化意识。任何一门自然形成与发展的语言,都有丰富的文化内涵,是民族文化和社会知识的重要载体。英语文化主要指英语国家的历史、地理、风土人情、传统习惯、生活方式、行为规范、价值观念等。接触与了解英语文化,有利于加深对语言学习的理解,激发学习兴趣,也有利于形成跨文化交际能力。首先,教师要多学习点“知识文化”。什么是“知识文化”
完全竞争厂商的需求量和收益分析:读书笔记十六
文水云淡
微观经济学对完全竞争市场的假设条件是:买卖人数多、产品同质化、进出行业自由、信息对称。根据这一假设,完全竞争市场的需求量就是市场上消费者的需求量的总和,它是一条向右下方倾斜的曲线,表示商品的需求量随价格的降低而增加,随价格的上涨而减少。最终会形成一个均衡的价格。厂商只有被动的接受这个均衡价格,并按照这个价格来组织生产,因此,厂商的需求曲线是一条平行线,价格是固定不变的,等于市场上的均衡价格。当均衡
利用K8S Statefulset搭建Etcd集群 - 本地存储
夜晓码农
大数据 Docker kubernetes etcd 容器
目录概述测试环境yaml配置service.yamlcluster.yamlQ&A参考链接概述公司因项目需要使用K8S部署ETCD集群供其他业务调用,网上搜索了解了下,一般K8S搭建ETCD集群大部分都是使用EtcdOperator来搭建。但是公司的项目运行在离线ARM架构平台,直接使用网上EtcdOperator代码,他们提供的镜像都是x86_64架构,经过Opeartor编译等尝试,最后都以失
《海底两万里》读书笔记|第十五章 知识渊博的船长
女人知书香
名师导读第二天,“我”在平台上见到了船长。这一次,船长竟主动与“我”聊了起来……渔网被他们拉上传来,里面有许多稀奇古怪的鱼:有因动作滑稽可笑而被称为丑鱼的枪机鱼,带有许多触腕的黑色喋鱼,带红色花纹的弯箭鱼,橄榄色的八目鳗,天蓝和银白相间的鲣鱼,还有华丽的金枪鱼等等。【形象描述】对于鱼的描写,从形状、颜色等特点着手,让读者感受到了大海的鱼类繁多。“它也有脉搏,有动脉,有偶然的痉挛,有和动物一样的血液
思考,快与慢
马唐
20180521,思考,快与慢之读书笔记:我们经常在自己出现失误的时候还信心满满,此时,旁观者往往比我们自己更容易发现这些失误。我们的主观判断是存在成见的:人们把相似度当成一种简单的启发手段,就是经验法则,来作艰难的判断。对这种启发性手段的依赖必然会造成其预测带有成见。对经验法则的依赖必然会导致人们判断时的成见。人们是根据从记忆中提取信息的容易程度来估测事情的重要程度的。本书重复出现的一个主题就是
《老房子开店日记》读书笔记-开店定位、20个创业故事
仙人刺美学
开店选址-创业流程-修缮预知-行销思考-用历史与文化连接开店经营每个人心中多多少少都会有一个老房子开店的生活理想。但是应该怎么实现呢?兴许不仅是有钱就可以做好的。《老房子开店日记》是去年在图书馆看到的,完全是书的名字吸引了我。后来让我的朋友十一买来送我做新年礼物的。看起来是一本很旧的书,不知道是不是正版,正面反面封面不知道是搞反了还是创意。但是整本书给我的感觉像是一本杂志!推荐大家在休闲的时间一边
浅学redis
撷思、
2024 数据库 redis
一、持久化1.为什么需要持久化?如果不将内存中的数据保存到磁盘,那么一旦服务器进程退出,服务器中数据也会消失,所以redis提供了持久化功能2.RDB(redisdatabase)redis配置中,默认使用RDB进行持久化。rdb保存的是dump.rdb文件。在指定时间间隔内,将内存中的数据快照写入磁盘,恢复时将快照文件存储到内存临时文件中,再次使用这个临时文件时,redis会单独创建(fork)
skynet cluster集群笔记
半夏知半秋
skynet 笔记 服务器 lua 系统架构
skynetcluster集群笔记前言cluster相关方法说明集群设计方案:集群中常遇到的问题:注意事项:前言skynet是一个基于事件驱动的分布式游戏服务器框架,支持构建高性能、高并发的网络程序。在skynet中,集群是指将多个节点连接在一起,共同协作完成任务的一个系统,一个skynet集群架构中涉及的一些名词如下:1.节点:skynet中的节点是指运行着skynet实例的独立服务器。每个节点
集群方式下的java Redis锁 lua脚本
成长之旅
后端 java
下面说一下集群方式redis下的原子锁带超时时间java代码如下:Listkeys=Collections.singletonList("test_key1");System.out.println("打印前::"+jedisCluster.get("test_key1"));//获取lua脚本这里你可以所以我是放在META-INF/scripts/redis/test.lua路径下,//获取到之
postgres数据库 查看数据表大小
MarcyTheLibrarian
linux pgsql 数据库 postgresql
1查看某个数据库大小selectpg_database_size('【数据库名】');2查看多个数据库大小selectpg_database.datname,pg_size_pretty(pg_database_size(pg_database.datname))ASsizefrompg_database;3按顺序查看索引selectindexrelname,pg_size_pretty(pg_r
《杜诗详注》读书笔记38:高都护骢马行
九曲奔流
按:高仙芝平少勃律,在天宝六载。是年,大食诸部七十二国皆降附。八载,入朝,诗云“飘飘远自流沙至”,又云“长安健儿不敢骑”,正其时也。九载,仙芝讨石国,俘其王以献,则知次年又往边疆矣。此诗当是天宝八载所作。黄云七载,梁云十一载,皆非。汉书·郑吉传:吉威震西域,遂并护车师以西北道,故号都护。都护之置,自吉始焉。注:并护南北二道,故谓之都。安西都护胡青骢,声价歘然来向东。此马临阵久无敌,与人一心成大功。
读书笔记:在峡江的转弯处
梧桐雨_
这几天培训时间,朋友带了一本书,说是一个全国优秀县委书记的人生随笔。我突然想起来,好像听两个人讲过这本书,都说这个县委书记了不得,正在巅峰时刻,却辞职搞公益事业了。当时就觉得还有这样的神人,有点难于置信。今天却有缘与之相遇,我喜不自胜,可以一看究竟了。谁知一看就停不下来了。这个县委书记出身湖北的一个小山村,按他的话说,“人生起点低在尘埃”,但是,他积极向上、勤奋自律、阳光感恩、一身正气。不说他在湖
Java二次开发海康SDK-对接门禁机一文全解
半自定义大剑仙
一文全解 java 前端 服务器 图像处理
写在最前SDK版本:CH-HCNetSDKV6.1.6.45_build20210302_win64参考文档:海康SDK使用手册_V6.1对接测试设备型号:DS-K1T671M设备序列号:E50247795业务目标使用门禁设备实现对人脸的抓拍,将抓拍的人脸与其对应的数据进行上传。业务流程图:业务流程节点解释:1.初始化SDK(NET_DVR_Init):进行海康提供开发库的载入,使用海康官方提供的
MySQL中查询所有表及其所有列的信息
临水逸
mysql 数据库
要在MySQL中查询所有表及其所有列的信息,可以结合使用INFORMATION_SCHEMA数据库和相关的系统视图。以下是分别查询所有表和所有列的SQL语句:查询所有表:SELECTTABLE_NAMEFROMINFORMATION_SCHEMA.TABLESWHERETABLE_SCHEMA='your_database_name';这里的'your_database_name'需要替换为你要查
读《牛奶可乐经济学》:最好的礼物是对方想要但又不舍得买的东西
李思服
007《牛奶可乐经济学》读书笔记干货分享:无论是做生意还是做销售工作,哪怕目前还没有上手,仅仅处于立志想经商的人,都应该先从理解社会上各行各业的那些看似矛盾的营销手段做起,日后才会合理看待市场上的商业行为。本书从两个经济学原理(成本效益原则和供求关系原理)出发,再从边际效益递减规律、折扣中的经济学、市场信号和心理学中的经济学去分析生活中各类商家常见的营销手段做法的必要性。首先是微观经济学领域中这两
底层逻辑的读书笔记
唐亚明
我读的这本书的作者是张羽,就是那个抖音平台30万粉丝,被网友称为“职场达人羽总”的。一开始的时候我读本书的目的是想了解什么是底层逻辑?在我的生活及工作中底层逻辑到底能给我提供那些支持?所谓底层逻辑就是从事物的底层、本质出发,寻找解决问题路径的思考方法。首先发现问题,其次可以对问题进行逐层分析,直到找到问题的本质,再从问题的本质出发,进一步深入,直到找到其解决方法。这个有点像剥洋葱,我喜欢吃洋葱最中
Redis命令之CLUSTER DELSLOTS
一条IT
CLUSTERDELSLOTSslot[slot...]起始版本:3.0.0时间复杂度:O(N)whereNisthetotalnumberofhashslotarguments在RedisCluster中,每个节点都会知道哪些主节点正在负责哪些特定的哈希槽DELSLOTS命令使一个特定的RedisCluster节点去忘记一个主节点正在负责的哈希槽,这些哈希槽通过参数指定。在已经接收到DELSLO
2022-11-03
二一明读书
昨天基本看完了《一本小小的写作小红书》。学到了一些基本的方法,但这本书主要写说明文的写法,而且是外国人,语法习惯、思维习惯和移位还是有区别的,所以要鉴别的来看这本书。我做了读书笔记。主要以下几个要点:一、文章的结构、风格、可读性和语法好比是把椅子的四条腿,非常重要。二“自上而写”写作法先写总结,开门见山三、分解事物把主题分解成二至四个主要部分,然后运用引导句。四、使用转折词使用转折词提示写作的方向
多线程编程之join()方法
周凡杨
java JOIN 多线程 编程 线程
现实生活中,有些工作是需要团队中成员依次完成的,这就涉及到了一个顺序问题。现在有T1、T2、T3三个工人,如何保证T2在T1执行完后执行,T3在T2执行完后执行?问题分析:首先问题中有三个实体,T1、T2、T3, 因为是多线程编程,所以都要设计成线程类。关键是怎么保证线程能依次执行完呢?
Java实现过程如下:
public class T1 implements Runnabl
java中switch的使用
bingyingao
java enum break continue
java中的switch仅支持case条件仅支持int、enum两种类型。
用enum的时候,不能直接写下列形式。
switch (timeType) {
case ProdtransTimeTypeEnum.DAILY:
break;
default:
br
hive having count 不能去重
daizj
hive 去重 having count 计数
hive在使用having count()是,不支持去重计数
hive (default)> select imei from t_test_phonenum where ds=20150701 group by imei having count(distinct phone_num)>1 limit 10;
FAILED: SemanticExcep
WebSphere对JSP的缓存
周凡杨
WAS JSP 缓存
对于线网上的工程,更新JSP到WebSphere后,有时会出现修改的jsp没有起作用,特别是改变了某jsp的样式后,在页面中没看到效果,这主要就是由于websphere中缓存的缘故,这就要清除WebSphere中jsp缓存。要清除WebSphere中JSP的缓存,就要找到WAS安装后的根目录。
现服务
设计模式总结
朱辉辉33
java 设计模式
1.工厂模式
1.1 工厂方法模式 (由一个工厂类管理构造方法)
1.1.1普通工厂模式(一个工厂类中只有一个方法)
1.1.2多工厂模式(一个工厂类中有多个方法)
1.1.3静态工厂模式(将工厂类中的方法变成静态方法)
&n
实例:供应商管理报表需求调研报告
老A不折腾
finereport 报表系统 报表软件 信息化选型
引言
随着企业集团的生产规模扩张,为支撑全球供应链管理,对于供应商的管理和采购过程的监控已经不局限于简单的交付以及价格的管理,目前采购及供应商管理各个环节的操作分别在不同的系统下进行,而各个数据源都独立存在,无法提供统一的数据支持;因此,为了实现对于数据分析以提供采购决策,建立报表体系成为必须。 业务目标
1、通过报表为采购决策提供数据分析与支撑
2、对供应商进行综合评估以及管理,合理管理和
mysql
林鹤霄
转载源:http://blog.sina.com.cn/s/blog_4f925fc30100rx5l.html
mysql -uroot -p
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)
[root@centos var]# service mysql
Linux下多线程堆栈查看工具(pstree、ps、pstack)
aigo
linux
原文:http://blog.csdn.net/yfkiss/article/details/6729364
1. pstree
pstree以树结构显示进程$ pstree -p work | grep adsshd(22669)---bash(22670)---ad_preprocess(4551)-+-{ad_preprocess}(4552) &n
html input与textarea 值改变事件
alxw4616
JavaScript
// 文本输入框(input) 文本域(textarea)值改变事件
// onpropertychange(IE) oninput(w3c)
$('input,textarea').on('propertychange input', function(event) {
console.log($(this).val())
});
String类的基本用法
百合不是茶
String
字符串的用法;
// 根据字节数组创建字符串
byte[] by = { 'a', 'b', 'c', 'd' };
String newByteString = new String(by);
1,length() 获取字符串的长度
&nbs
JDK1.5 Semaphore实例
bijian1013
java thread java多线程 Semaphore
Semaphore类
一个计数信号量。从概念上讲,信号量维护了一个许可集合。如有必要,在许可可用前会阻塞每一个 acquire(),然后再获取该许可。每个 release() 添加一个许可,从而可能释放一个正在阻塞的获取者。但是,不使用实际的许可对象,Semaphore 只对可用许可的号码进行计数,并采取相应的行动。
S
使用GZip来压缩传输量
bijian1013
java GZip
启动GZip压缩要用到一个开源的Filter:PJL Compressing Filter。这个Filter自1.5.0开始该工程开始构建于JDK5.0,因此在JDK1.4环境下只能使用1.4.6。
PJL Compressi
【Java范型三】Java范型详解之范型类型通配符
bit1129
java
定义如下一个简单的范型类,
package com.tom.lang.generics;
public class Generics<T> {
private T value;
public Generics(T value) {
this.value = value;
}
}
【Hadoop十二】HDFS常用命令
bit1129
hadoop
1. 修改日志文件查看器
hdfs oev -i edits_0000000000000000081-0000000000000000089 -o edits.xml
cat edits.xml
修改日志文件转储为xml格式的edits.xml文件,其中每条RECORD就是一个操作事务日志
2. fsimage查看HDFS中的块信息等
&nb
怎样区别nginx中rewrite时break和last
ronin47
在使用nginx配置rewrite中经常会遇到有的地方用last并不能工作,换成break就可以,其中的原理是对于根目录的理解有所区别,按我的测试结果大致是这样的。
location /
{
proxy_pass http://test;
java-21.中兴面试题 输入两个整数 n 和 m ,从数列 1 , 2 , 3.......n 中随意取几个数 , 使其和等于 m
bylijinnan
java
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
public class CombinationToSum {
/*
第21 题
2010 年中兴面试题
编程求解:
输入两个整数 n 和 m ,从数列 1 , 2 , 3.......n 中随意取几个数 ,
使其和等
eclipse svn 帐号密码修改问题
开窍的石头
eclipse SVN svn帐号密码修改
问题描述:
Eclipse的SVN插件Subclipse做得很好,在svn操作方面提供了很强大丰富的功能。但到目前为止,该插件对svn用户的概念极为淡薄,不但不能方便地切换用户,而且一旦用户的帐号、密码保存之后,就无法再变更了。
解决思路:
删除subclipse记录的帐号、密码信息,重新输入
[电子商务]传统商务活动与互联网的结合
comsci
电子商务
某一个传统名牌产品,过去销售的地点就在某些特定的地区和阶层,现在进入互联网之后,用户的数量群突然扩大了无数倍,但是,这种产品潜在的劣势也被放大了无数倍,这种销售利润与经营风险同步放大的效应,在最近几年将会频繁出现。。。。
如何避免销售量和利润率增加的
java 解析 properties-使用 Properties-可以指定配置文件路径
cuityang
java properties
#mq
xdr.mq.url=tcp://192.168.100.15:61618;
import java.io.IOException;
import java.util.Properties;
public class Test {
String conf = "log4j.properties";
private static final
Java核心问题集锦
darrenzhu
java 基础 核心 难点
注意,这里的参考文章基本来自Effective Java和jdk源码
1)ConcurrentModificationException
当你用for each遍历一个list时,如果你在循环主体代码中修改list中的元素,将会得到这个Exception,解决的办法是:
1)用listIterator, 它支持在遍历的过程中修改元素,
2)不用listIterator, new一个
1分钟学会Markdown语法
dcj3sjt126com
markdown
markdown 简明语法 基本符号
*,-,+ 3个符号效果都一样,这3个符号被称为 Markdown符号
空白行表示另起一个段落
`是表示inline代码,tab是用来标记 代码段,分别对应html的code,pre标签
换行
单一段落( <p>) 用一个空白行
连续两个空格 会变成一个 <br>
连续3个符号,然后是空行
Gson使用二(GsonBuilder)
eksliang
json gson GsonBuilder
转载请出自出处:http://eksliang.iteye.com/blog/2175473 一.概述
GsonBuilder用来定制java跟json之间的转换格式
二.基本使用
实体测试类:
温馨提示:默认情况下@Expose注解是不起作用的,除非你用GsonBuilder创建Gson的时候调用了GsonBuilder.excludeField
报ClassNotFoundException: Didn't find class "...Activity" on path: DexPathList
gundumw100
android
有一个工程,本来运行是正常的,我想把它移植到另一台PC上,结果报:
java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.mobovip.bgr/com.mobovip.bgr.MainActivity}: java.lang.ClassNotFoundException: Didn't f
JavaWeb之JSP指令
ihuning
javaweb
要点
JSP指令简介
page指令
include指令
JSP指令简介
JSP指令(directive)是为JSP引擎而设计的,它们并不直接产生任何可见输出,而只是告诉引擎如何处理JSP页面中的其余部分。
JSP指令的基本语法格式:
<%@ 指令 属性名="
mac上编译FFmpeg跑ios
啸笑天
ffmpeg
1、下载文件:https://github.com/libav/gas-preprocessor, 复制gas-preprocessor.pl到/usr/local/bin/下, 修改文件权限:chmod 777 /usr/local/bin/gas-preprocessor.pl
2、安装yasm-1.2.0
curl http://www.tortall.net/projects/yasm
sql mysql oracle中字符串连接
macroli
oracle sql mysql SQL Server
有的时候,我们有需要将由不同栏位获得的资料串连在一起。每一种资料库都有提供方法来达到这个目的:
MySQL: CONCAT()
Oracle: CONCAT(), ||
SQL Server: +
CONCAT() 的语法如下:
Mysql 中 CONCAT(字串1, 字串2, 字串3, ...): 将字串1、字串2、字串3,等字串连在一起。
请注意,Oracle的CON
Git fatal: unab SSL certificate problem: unable to get local issuer ce rtificate
qiaolevip
学习永无止境 每天进步一点点 git 纵观千象
// 报错如下:
$ git pull origin master
fatal: unable to access 'https://git.xxx.com/': SSL certificate problem: unable to get local issuer ce
rtificate
// 原因:
由于git最新版默认使用ssl安全验证,但是我们是使用的git未设
windows命令行设置wifi
surfingll
windows wifi 笔记本wifi
还没有讨厌无线wifi的无尽广告么,还在耐心等待它慢慢启动么
教你命令行设置 笔记本电脑wifi:
1、开启wifi命令
netsh wlan set hostednetwork mode=allow ssid=surf8 key=bb123456
netsh wlan start hostednetwork
pause
其中pause是等待输入,可以去掉
2、
Linux(Ubuntu)下安装sysv-rc-conf
wmlJava
linux ubuntu sysv-rc-conf
安装:sudo apt-get install sysv-rc-conf 使用:sudo sysv-rc-conf
操作界面十分简洁,你可以用鼠标点击,也可以用键盘方向键定位,用空格键选择,用Ctrl+N翻下一页,用Ctrl+P翻上一页,用Q退出。
背景知识
sysv-rc-conf是一个强大的服务管理程序,群众的意见是sysv-rc-conf比chkconf
svn切换环境,重发布应用多了javaee标签前缀
zengshaotao
javaee
更换了开发环境,从杭州,改变到了上海。svn的地址肯定要切换的,切换之前需要将原svn自带的.svn文件信息删除,可手动删除,也可通过废弃原来的svn位置提示删除.svn时删除。
然后就是按照最新的svn地址和规范建立相关的目录信息,再将原来的纯代码信息上传到新的环境。然后再重新检出,这样每次修改后就可以看到哪些文件被修改过,这对于增量发布的规范特别有用。
检出