转载请注明:http://duanple.blog.163.com/blog/static/709717672010961173782/ 作者 phylips@bmy
摘要
Bigtable是设计用来管理那些可能达到很大大小(比如可能是存储在数千台服务器上的数PB的数据)的结构化数据的分布式存储系统。Google的很多项目都将数据存储在Bigtable中,比如网页索引,google 地球,google金融。这些应用对Bigtable提出了很多不同的要求,无论是数据大小(从单纯的URL到包含图片附件的网页)还是延时需求。尽管存在这些各种不同的需求,Bigtable成功地为google的所有这些产品提供了一个灵活的,高性能的解决方案。在这篇论文中,我们将描述Bigtable所提供的允许客户端动态控制数据分布和格式的简单数据模型,此外还会描述Bigtable的设计和实现。
1.导引
在过去的2年半时间里,我们设计,实现,部署了一个称为Bigtable的用来管理google的数据的分布式存储系统。Bigtable的设计使它可以可靠地扩展到成PB的数据以及数千台机器上。Bigtable成功的实现了这几个目标:广泛的适用性,可扩展性,高性能以及高可用性。目前,Bigtable已经被包括Google分析,google金融,Orkut,个性化搜索,Writely和google地球在内的60多个google产品和项目所使用。这些产品使用Bigtable用于处理各种不同的工作负载类型,从面向吞吐率的批处理任务到时延敏感的面向终端用户的数据服务。这些产品所使用的Bigtable集群也跨越了广泛的配置规模,从几台机器到存储了几百TB数据的上千台服务器。
在很多方面,Bigtable都类似于数据库:它与数据库采用了很多相同的实现策略。目前的并行数据库和主存数据库已经成功实现了可扩展性和高性能,但是Bigtable提供了与这些系统不同的接口。Bigtable并不支持一个完整的关系数据模型,而是给用户提供了一个可以动态控制数据分布和格式的简单数据模型,允许用户将数据的局部性属性体现在底层的数据存储上。数据使用可以是任意字符串的行列名称进行索引。Bigtable将数据看做是未经解释的字符串,尽管用户经常将各种形式的结构化或半结构化的数据存储到这些字符串里。用户可以通过在schema中的细心选择来控制数据的locality。最后,Bigtable的schema参数还允许用户选择从磁盘还是内存获取数据。
第2节更加详细的描述了该数据模型。第3节提供了关于用户API的概览。第4节简要描述了Bigtable所依赖的底层软件。第5节描述了Bigtable的基本实现。第6节描述了我们为提高Bigtable的性能使用的一些技巧。第7节提供了一些对于Bigtable的性能测量数据。第8节展示了几个Google内部的Bigtable的使用实例。第9节讨论了我们在设计支持Bigtable所学到的一些经验教训。最后第10节描述了相关工作,第11节进行了总结。
2.数据模型
Bigtable是一个稀疏的,分布式的一致性多维有序map。这个map是通过行关键字,列关键字以及时间戳进行索引的;map中的每个值都是一个未经解释的字节数组。
(row:string,column:string,time:int64) -> string
我们在对于这种类Bigtable系统的潜在使用场景进行了大量考察后,最终确定了这个数据模型。举一个影响到我们的某些设计决策的具体例子,比如我们想保存一份可以被很多工程使用的一大集网页及其相关信息的拷贝。我们把这个表称为webtable,在这个表中,我们可以使用URL作为行关键字,网页的各种信息作为列名称,将网页的内容作为表的内容存储:获取的时候还需要在列上加上时间戳,如图1所示。
表中的行关键字是大字符串(目前最大可以到64KB,尽管对于大多数用户来说最常用的是10-100字节)。在一个行关键字下的数据读写是原子性的(无论这一行有多少个不同的列被读写),这个设计使得用户在对相同行的并发更新出现时,更容易理解系统的行为。
Bigtable按照行关键字的字典序来维护数据。行组{row range,将它翻译为行组,一个row range可能由多个行组成}是可以动态划分的。每个行组叫做一个tablet,是数据存放以及负载平衡的单位。这样,对于一个短的行组的读就会很有效,而且只需要与少数的机器进行通信。客户端可以通过选择行关键字来利用这个属性,这样它们可以为数据访问得到好的局部性。比如,在webtable里,相同域名的网页可以通过将URL中的域名反转而使他们放在连续的行里来组织到一块。比如我们将网页maps.google.com/index.html的数据存放在关键字com.google.maps/index.html下。将相同域名的网页存储在邻近位置可以使对主机或域名的分析更加有效。
列族
不同的列关键字可以被分组到一个集合,我们把这样的一个集合称为一个列族,它是基本的访问控制单元。存储在同一个列族的数据通常是相同类型的(我们将同一列族的数据压缩在一块)。在数据能够存储到某个列族的列关键字下之前,必须首先要创建该列族。我们假设在一个表中不同列族的数目应该比较小(最多数百个),而且在操作过程中这些列族应该很少变化。与之相比,一个表的列数目可以没有限制。
一个列关键字是使用如下的字符来命名的:family:qualifier。列族名称必须是可打印的,但是qualifier可能是任意字符串。比如webtable有一个列族是language,它存储了网页所使用的语言。在language列族里,我们只使用了一个列关键字,里面存储了每个网页的language id。该表的另一个列族是anchor,在该列族的每个列关键字代表一个单独的anchor,如图1所示。Qualifier是站点的名称,里面的内容是链接文本。
访问控制以及磁盘的内存分配都是在列族级别进行的。在webtable这个例子中,这些控制允许我们管理不同类型的应用:一些可能会添加新的基础数据,一些可能读取这些基础数据来创建新的列族,一些可能只需要查看现有数据(甚至可能因为隐私策略不需要查看所有现有数据)。
时间戳
Bigtable里的每个cell可以包含相同数据的多个版本;这些不同的版本是通过时间戳索引的。Bigtable的时间戳是一个64位的整数。它们可以由Bigtable来赋值,在这种情况下它们以毫秒来代表时间。也可以由客户端应用程序显式分配。应用程序为了避免冲突必须能够自己生成唯一的时间戳。一个cell的不同版本是按照时间戳降序排列,这样最近的版本可以被首先读到。
为了使不同版本的数据管理更简单,我们支持2个针对每个列族的设定来告诉Bigtable可以对cell中的数据版本进行自动的垃圾回收。用户可以指定最近的哪几个版本需要保存,或者保存那些足够新的版本(比如只保存那些最近7天写的数据)。
在我们的webtable中,我们将爬取的网页的时间戳存储在内容里:这些时间说明了这些网页的不同版本分别是在何时被抓取的。前面描述的垃圾回收机制,使我们只保存每个网页最新的三个版本。
3. API
Bigtable API提供了一些函数用于表及列族的创建和删除。它也提供了一些用于改变集群,表格及列族元数据的函数,比如访问控制权限。
客户端应用程序可以写或者删除Bigtable里的值,从行里查找值或者在表中的一个数据子集中进行迭代。图2展示了使用RowMutation执行一系列更新的C++代码(为了保持简单省略了不相关的细节)。Apply调用对webtable执行了一个原子性的变更操作:给www.cnn.com增加一个anchor,然后删除另一个anchor。
图3展示的c++代码使用Scanner来在一个特殊行上的所有anchor进行迭代,用户可以在多个列族上进行迭代,存在几种机制来对扫描到的行,列,时间戳进行过滤。比如我们可以限制只扫描那些与正则表达式”anchor:*.cnn.com”匹配的列,或者那些时间戳距离当前时间10天以内的anchor。
Bigtable提供了几种其他的feature允许用户使用更复杂的方式熟练控制数据。首先,Bigtable支持单行事务,能够支持对存储在一个行关键字上的执行原子性的读写修改序列。Bigtable当前并不支持跨行的事务,尽管它提供了一个多个用户的跨行写的接口。其次,Bigtable允许用户将cell作为一个整数计数器来使用。最后,Bigtable支持在服务器地址空间内执行一个客户端脚本。这些脚本是使用google内部开发的数据处理语言sawzall编写的。当前,我们基于Sawzall的API不允许客户端脚本向Bigtable中写回,但是它允许进行各种形式的数据转换,基于各种表达式的过滤以及大量的统计操作符。
Bigtable可以与MapReduce(google内部开发的一个运行大规模并行程序的框架)一起使用。我们写了很多wrapper它允许将Bigtable作为输入源或者输出目标。
4. 基础构件
Bigtable是建立在google的其他几个设施之上。Bigtable使用GFS来存储日志和数据文件。Bigtable集群通常运行在一个运行着大量其他分布式应用的共享机器池上。Bigtable依赖于一个集群管理系统进行job调度,共享机器上的资源管理,处理机器失败以及监控机器状态。
Bigtable内部采用Google SSTable文件格式来存储数据。一个SSTable提供了一个一致性的,有序的从key到value的不可变map,key和value都是任意的字节串。操作通常是通过一个给定的key来查找相应的value,或者在一个给定的key range上迭代所有的key/value对。每个SSTable内部包含一系列的块(通常每个块是64KB大小,但是该大小是可配置的)。一个块索引(保存在SSTable的尾部)是用来定位block的,当SSTable打开时该索引会被加载到内存。一次查找可以通过一次磁盘访问完成:首先通过在内存中的索引进行一次二分查找找到相应的块,然后从磁盘中读取该块。另外,一个SSTable可以被完全映射到内存,这样就不需要我们接触磁盘就可以执行所有的查找和扫描。{关于SSTable(StaticSearchTable)的具体格式可以参考YunTable开发日记(4)-BigTable的存储模型,中对HBASE的HFile的介绍}
Bigtable依赖于一个高可用的一致性分布式锁服务Chubby。Chubby由5个活动副本组成,其中的一个选为master处理请求。当大部分的副本运行并且可以相互通信时,该服务就是活的。Chubby使用Paxos算法来在出现失败时,保持副本的一致性。Chubby提供了一个由目录和小文件组成的名字空间。每个文件或者目录可以当作一个锁来使用,对于一个文件的读写是原子性的。Chubby的客户端库为Chubby文件提供一致性缓存。每个Chubby客户端维护这一个与Chubby服务的会话。如果在租约有效时间内无法更新会话的租约,客户端的会话就会过期。当一个客户端会话过期后,它会丢失所有的锁和打开的文件句柄。Chubby客户端也会在Chubby文件和目录上注册回调函数来处理这些变更或者会话的过期。
Bigtable使用Chubby来完成各种任务:保证任意时刻最多只有一个活动的master;存储Bigtable数据的bootstrap location(参见5.2节);发现tablet服务器以及finalize tablet服务器的死亡(参见5.2节);保存Bigtable schema信息(每个表的列族信息);存储访问控制列表。如果chubby在一段时间内不可用,Bigtable也会不可用。我们最近在使用了11个chubby实例的14个Bigtable集群进行了测量。由于Chubby不可用而造成的存储在Bigtable上的数据不可用的平均概率是0.0047%。对于单个集群来说,由于Chubby不可用造成的这个概率是0.0326%。
5. 实现
Bigtable实现有3个主要的组件:每个客户端需要链接的库,一个master服务器,很多tablet服务器。tablet服务器可以从一个集群中动态添加(或者删除)来适应工作负载的动态变化。
Master负责将tablet分配到tablet服务器,检测tablet服务器的添加和过期,平衡tablet服务器负载,GFS文件的垃圾回收。另外,它还会处理schema的变化,比如表和列族的创建。
每个tablet服务器管理一个tablets集合(通常每个tablet服务器有10到1000个tablet)。Tablet服务器负责它已经加载的那些tablet的读写请求,也会将那些过于大的tablet进行分割。{tablet服务器本身实际上也是GFS的用户,它们只是负载它加载的那些tablet的管理,这些tablet的物理存储并不一定存放在管理它的服务器上,底层的存储是由GFS完成的,tablet服务器可以只调用它的接口来完成相应任务。而METADATA表中的位置信息应该是指某个tablet由哪个tablet服务器管理,而不是物理上存储在哪个机器上。}
正如很多单master的分布式存储系统,客户端数据的移动并不会经过master:客户端直接与tablet服务器进行通信来进行读写。因为Bigtable客户端并不依赖于master得到tablet的位置信息,大部分的客户端从来不会于master通信。所以,master实际中通常都是负载很轻的。
Bigtable集群存储了大量的表。每个表由一系列的tablet组成,每个tablet包含一个行组的所有相关数据。一开始,每个表由一个tablet组成。随着表格的增长,它会自动分割成多个tablet,它们大小默认是100-200MB。
5.1 Tablet存放位置
我们使用一个类似于B+树的三级结构来存储tablet的放置信息如图4。
第一级是一个存储在Chubby的包含了root tablet位置信息的文件。root tablet包含了在一个特殊的METADATA表里的所有tablet的位置信息{root tablet实际上是METADATA表的第一个tablet,它存储了该表其他的tablet的位置信息}。每个METADATA tablet包含了一集用户tablet的位置。Root tablet仅仅是METADATA表的第一个tablet,但是是特殊对待的-它永远不会被分割-为了保证tablet位置信息的层次结构不会超过3级。
METADATA表的每一个行关键字(由tablet所属的表标识符和它的结束行组成)下存储了一个tablet的位置。每个METADATA行在内存中大概存储了1KB数据。我们限制METADATA的tablet的大小为128MB,我们的三级层次结构足以用来寻址2^34个tablet(如果tablet按照128MB算,就是2^61字节){root tablet大小为128M,每个行1KB,那么它就可以存储128*2^20/2^10=128*2^10个METADATA tablet,同样的,每个METADATA tablet可以存储128*2^10个普通tablet,这样总共可以存储128*2^10*128*2^10即2^34个普通tablet,每个tablet又将近1KB数据,这样算起来存储这些元信息就需要4TB的数据,所以该METADATA表也不可能全部放入内存,而是采用与普通的表一样的存储方式,放在GFS上。但是会把某些特殊信息放在内存中,比如第6节提到的:METADATA中的location列族会被放入内存 }。
客户端库会缓存tablet的位置信息。如果客户端不知道某个tablet的信息,或者发现缓存的位置信息是错误的,那么它就会递归地在tablet位置存储结构中查找。如果客户端缓存是空的,定位算法需要三次网络往返,包括从Chubby的一次读操作。如果客户端缓存是陈旧的,定位算法将需要多达6次的往返,因为陈旧的缓存值只有在不命中时才会被发现(假设METADATA tablet并不会经常移动)。尽管Tablet位置信息是存储在内存中(如上所述),不需要访问GFS,但是我们还是通过在客户端库里进行预取来降低花费:当读取METADATA表时,它会读取不止一个tablet的信息。
我们也会将一些额外信息存放在METADATA表里,包括对于每个tablet有关的事件日志(比如一个服务器何时开始提供服务)。这些信息对于调试和性能分析很有帮助。
5.2 tablet分配
每个Tablet一次只会分配给一个tablet服务器。Master保存了现有的活着的tablet服务器集合的所有行踪,tablet服务器当前分配的tablet,哪些tablet未被分配。当一个tablet没有被分配并且有一个可以存储该tablet的tablet服务器存在时,master通过给那个tablet服务器发送一个tablet负载请求来分配该tablet。
Bigtable使用Chubby来追踪tablet服务器的状态。当一个tablet服务器启动时,它创建并获取一个在给定的Chubby目录上的唯一命名的文件的独占锁。Master通过监控这个目录(服务器目录)来发现tablet服务器。Tablet服务器如果丢失了它的独占锁(比如由于网络问题)就停止它上面的tablet服务。一个tablet服务器会尝试重新获取在该文件上的独占锁,只要该文件还存在。如果该文件也不存在了,那么tablet服务器就永远无法提供该服务了。当一个tablet服务器停止(比如集群管理系统从集群中删除了该tablet 服务器机器),它就会尝试释放这个锁这样master就可以更快地重新分配它上面的tablets了。
Master负责检测一个tablet服务器何时停止提供服务,以尽快重新安排它的tablets。为了进行检测,master周期性的向每个tablet服务器询问它的锁状态。如果一个tablet服务器报告它丢失了它的锁,或者master在它的几次尝试中不能到达一个服务器,master会尝试获取该服务器的锁。如果master可以获取该锁,那么Chubby就是活的,而tablet服务器要么是死的要么因为某些问题而无法到达Chubby,那么master就可以通过删除它的server文件来使得该tablet服务器永远都不能提供服务。一旦一个服务器的文件被删除了,master就可以将之前分配给该服务器的所有tablet移到那些为分配的tablet集合中。为了保证一个Bigtable集群不会因为与master和Chubby间的网络问题而变得脆弱,如果master的Chubby会话过期了,master会自杀。然而,如前面所述,master的失败并不会改变tablet服务器的tablet分配。
当master被集群管理系统启动后,在它可以改变tablets之前需要知道它们当前的分配状态。Master在启动时执行如下步骤:1.master在Chubby获得一个唯一的master锁,该锁可以防止出现同时生成多个master实例。2.master扫描Chubby的服务器目录来找到所有活着的服务器。3.master与活着的tablet服务器通信来发现每个服务器安排了哪些tablet。4.master扫描METADATA表来找到tablet集合。当扫描中碰到一个未被分配的tablet,master会将它添加到未分配的tablet集合,并对这个tablet进行分配。
在METADATA 的tablets未被分配之前,对于METADATA的扫描不能进行。因此在开始扫描之前(步骤4),如果在步骤3没有发现对于root tablet的分配,master会将root tablet添加到未分配tablets集合中。这个添加将会使root tablet变得可以被分配。因为root tablet包含所有METADATA tablets的名称,master当扫描完root tablet后就能知道METADATA的所有的tablets。
只有当一个表被创建,现有的两个tablets合并为一个,或者一个tablet被分割为一个时,现有的tablet集合才会发生变化。Master能够追踪所有的这些变化,因为它负责维护它们。Tablet分割需要特殊对待因为它们是由一个tablet服务器启动的。Tablet服务器通过将新的tablet的信息记录到METADATA表中来提交这个分割。当分割提交后,它会通知master。为了防止分割通知丢失(因为tablet服务器或者master死了),当master向tablet服务器请求加载刚刚发生分割的那个tablet时,它会检测到这个新的tablet。Tablet服务器会将这个分割通知master,因为它在METADATA表中的tablet键值仅包含了master让它加载的那个tablet的一部分。{假设master没有收到这个分割通知,那么它所记录的tablet与METADATA表中的就是不一致的,这样在它让tablet服务器加载该tablet时就会发现该不一致}。
5.3 tablet服务
Tablet的持久性状态是通过GFS进行存储的,如图5所示。
更新是提交到一个保存了redo记录的提交日志里。在这些更新里,最近提交的那些被保存到内存中一个叫做memtable的有序缓存里,老的更新则被保存在一系列的SSTable中。为了恢复一个tablet,tablet服务器从METADATA表中读取该tablet的元数据。元数据中包含组成该tablet的SSTable列表,以及一系列的redo点(指向那些包含该tablet数据的commit日志条目)的集合。Tablet服务器将所有SSTable的索引读入内存,然后通过应用那些从redo点开始以及提交的更新操作来重新构建memtable。
{更新操作肯定会被保存到commit log里,但是当某个服务器挂掉时,它那些保存在memtable的最新的更新就不存在了,而redo点应该就是记录已保存到SSTable的与还在memtable中的操作的分界点,这样通过重新执行它之后的那些操作就可以将memtable重建}{redo点何时被更新?有多少个commit log?参见第6节}
当一个写操作到达一个tablet服务器时,服务器首先检查它的格式是否合法,发送者是否有权限进行该操作。权限检查是通过从Chubby读取一个允许的写操作者列表(通常它直接存在于Chubby的客户端缓存中)完成的。一个合法的变更会被写入到已提交日志里。操作的提交可以通过分组执行来提高大量小变更操作出现时的吞吐率,当该写操作提交后,它的内容会被插入到memtable里。
当一个读操作到达一个tablet服务器时,类似的首先要进行格式和权限检查。一个合法的读操作将会在一系列SSTable和memtable的一个合并视图上执行{因为SSTable一旦写入就不可变,这样就使得更新操作必须写到新的SSTable中,这样就导致同一个key值可能在多个SSTable中出现,这样读取时就必须读取多个SSTable才能得到它真实的最终状态}。因为SSTable和memtable都是字典有序的数据结构,因此可以很快生成这个视图。{为了读取一个key时,要读入所有的SSTable,所以第6节有一个针对该问题的优化Bloom Filter。此外伴随着SSTable的增多,这种视图合并也会变得低效,所以也引出了下面的Compation}
当tablet发生分割或者合并时,也可以继续接受读写操作。
5.4 compaction
伴随着写操作的执行,memtable的大小会逐渐变大。当memtable大小增长到一个阈值,这个memtable就会被冻结,一个新的memtable被创建,被冻结的旧的memtable会被转化为一个SSTable写入GFS。这个minor compaction过程有两个目的:降低tablet server的内存使用,降低该tablet服务器挂掉时需要从已提交日志中读取的数据大小。当compaction发生时,也可以继续接受读写操作。
每次minor Compation会创建一个新的SSTable。如果这个行为持续的进行而不检查,那么读操作就可能会需要从大量的SSTable中合并它们的更新。我们通过周期性的执行一个merging compaction来将这样的文件数目限制在一定范围内。一个merging compaction读取多个SStable和memtable,然后写入到一个新的SSTable(形成一个最终的归并视图)。一旦这个compaction结束,这些SSTable和memtable就可以丢弃了。
将多个SSTable重新写入到一个SSTable的merging compaction称为主compaction。由非主compaction产生的SSTable里可以包含一些在旧的SSTable中仍然存活但是目前已经被删除的数据。另一方面,一个主compaction产生的SSTable不会包含删除操作信息或者已删除数据。Bigtable循环扫描它所有的tablet,周期的对它们执行主compaction。这些主compaction使得Bigtable可以回收那些被已删除的数据使用的资源。这也保证那些已经删除的数据在一定时间内会从系统中消失,这对于那些存储敏感数据的服务来说很重要。
6 技巧
前面一节描述的实现需要大量的技巧来到达用户所需要的高性能,可用性,可靠性。这一节更细节地描述下实现的各个部分,着重讲述下使用的这些技巧。
局部性群组(对应一个SSTable)
用户可以将多个列族组织为一个局部性群组。对于每个tablet里的每个局部性群组都会生成一个单独的SSTable。将那些通常不会被一起访问的列族分离到独立的局部性群组可以增加访问的效率。比如,webtable的关于网页的元数据(比如语言,校验和)可放到一个局部性群组,网页内容可以放到另一个群组里:这样一个访问元数据的应用程序就不需要读取所有网页的内容。
另外,一些有用的tuning参数也可以以局部性群组为单位进行设置。比如一个局部性群组可以声明为放入内存的。对于声明为放入内存的局部性群组的SSTable在需要时才会加载到tablet服务器的内存中。一旦加载之后,对于该局部性群组的访问就不需要访问磁盘。这个特点对于那些需要经常访问的小片数据很有用:比如在Bigtable内部我们将它应用在METADATA表的location列族上。
压缩
用户可以控制对于一个局部性群组的SSTables是否进行压缩,以及使用哪种压缩格式。用户指定的压缩格式会应用在SSTable的每个块上(块大小可以通过一个局部性群组的参数进行控制)。对于每个块单独进行压缩,尽管这使我们丢失了一些空间,但是这使得我们不需要解压整个文件就可以读取SSTable的部分内容。很多用户使用一个两遍压缩模式,第一遍压缩使用Bentley and McIlroy模式,该模式在一个很大的窗口大小里压缩普通的长字符串。第二遍压缩了一个快速压缩算法,该算法在一个小的16KB窗口大小内查找重复。这两遍压缩都很快速,压缩速率在100-200MB/s,解压速率在400-1000MB/s。
尽管在选择压缩算法时,我们更重视速率而不是空间的减少,但是这个两遍压缩模式或做的出奇地好。比如,在webtable里我们使用这种压缩模式存储网页内容。实验中,我们在一个压缩的局部性群组里存储了大量文档。为了实验目的,我们将文档的版本数限制为1。该压缩模式达到了10 :1的压缩率。这比通常的Gzip 对于HTML网页的3:1或4:1的压缩率要好多了。这是由我们的webtable的行分布方式造成的:来自相同主机的网页被存储在相邻的位置。这使Bentley and McIlroy算法可以识别出来自相同站点的大量固有模式。很多应用程序,不仅仅是webtable,选择的行名称使得类似数据会聚集在一起,因此达到了很好的压缩率。当我们在Bigtable中存储相同值的多个版本时压缩率会更好。
为了读性能进行缓存
为了提高读性能,tablet服务器使用一个二级缓存。扫描缓存是一个用来缓存由SSTable返回给tablet服务器的key-value对的高级缓存。块缓存是用来缓存从GFS读取的SSTable块的低级缓存。扫描缓存主要用于那些倾向于重复读取相同数据的应用,块缓存则用于那些倾向于从最近读取的数据的邻近位置读取数据的应用(比如顺序读,或者读取一个热点行内的相同局部性群组里的不同列值)。
Bloom Filters
正如5.3节所描述的,一个读操作需要从组成该tablet的所有SSTable里读取。如果这些SSTable不在内存,就需要很多磁盘操作。通过让用户为某个局部性群组的SSTables指定对应的Bloom filters,可以降低磁盘访问次数。一个Bloom Filter允许我们查询对应的SSTable是否包含某个给定的row/column对的数据。对于特定的应用程序来说,只需要很少的tablet服务器内存来保存Bloom Filter,但可以大大减少读操作所需要的磁盘操作。同时Bloom Filter可以避免那些对于不存在的行列的查找访问磁盘。
提交日志实现
如果我们为每个tablet的提交日志建立一个独立的日志文件,就会使得大量的文件需要并发写入GFS。由于每个GFS服务器的底层文件系统实现,这些写操作会引起在不同物理日志文件上的大量的磁盘寻道。另外,每个tablet一个日志文件会降低分组提交优化的效率。为了解决这些问题,每个tablet服务器将更新操作append一个日志文件里,将对于不同的tablet的变更放到同一个物理日志文件里。
使用一个日志为正常操作提供了很明显的性能好处,但是使恢复变复杂了。当一个tablet服务器挂掉后,它负责的那些tablet需要移动到大量其他的tablet服务器上:每个服务器通常都会加载一些该服务器的tablet。为了恢复一个tablet的状态,新的tablet服务器需要通过原来那个tablet服务器的提交日志重新应用这个tablet的变更操作。然而对于这些tablet的变更是混在同一个日志文件里的。一种方法是,每个新的tablet服务器全部读取这个日志文件,然后仅应用那些它需要恢复的tablet的变更操作。然而,在这种模式下,如果失败的那台tablet服务器的tablet被分配到了100个机器,那么这个日志文件就需要读取100次。
我们通过对提交日志里的entry根据
进行排序避免了重复的日志读取。在已排序的输出中,对于一个tablet的所有变更都是连续的,因此可以通过一次的磁盘寻道和顺序读操作就可以完成读取。为了并行化排序,我们将该日志文件划分为64MB大小的段,在不同的tablet服务器上对它们进行排序。排序过程是由master协调进行的,当一个tablet服务器指出它需要从一个日志文件中恢复变更时开始启动。
将提交日志写入GFS有时候可能因为各种原因导致性能抖动(比如GFS服务器处在繁重的写操作中,或者网络处于拥塞或者重载)。为了避免变更操作受到GFS延时的影响,每个tablet服务器实际上有2个写日志线程,每个写它们各自的日志文件,在同一时间只有一个处在活跃期。如果对于活动日志文件的写性能急剧下降,它就会切换到另一个线程,在提交日志队列中的那些变更操作将由这个新的活动线程负责写入。日志条目里包含序列号,这就使得恢复过程中可以删除那些由于日志切换过程造成的重复条目。
加速tablet恢复
如果master将tablet从一个tablet服务器移动到另一个,源tablet服务器会首先在该tablet上进行一个minor compaction。这个compaction将会减少在tablet服务器的日志里的uncompacted状态数。当compaction结束后,tablet服务器停止针对该tablet的服务。在彻底卸载该tablet之前,tablet服务器再进行一次minor compaction(通常是很快速的)来消除那些上次minor compaction之后该tablet服务上剩余的uncompacted状态。当第二次的minor compaction结束后,该tablet就可以直接由另一个tablet服务器加载而不需要从日志条目中进行恢复。{通过这个过程也可以看出,tablet服务器只负责管理memtable和SSTable,对于底层的存储它并不负责,当tablet迁移到另一个服务器时,它在GFS的存储并没有变,变的只是管理它的tablet服务器,而新的tablet服务器也不需要进行数据移动之类的操作,因为它同样可以看到原来的GFS文件。}
利用不可变性
除了SSTable缓存,Bigtable系统的各部分通过利用”SSTable生成之后就是不可变的”这个事实也得到了大大的简化。比如我们从SSTable中读取时,不需要对文件系统的访问进行任何同步。这样,在行上的并发控制就可以有效的实现。唯一的可以读写的可变数据结构就是memtable。为了减少在memtable读取时的竞争,我们对每个memtable行进行写时复制,这就允许读写并行处理。
因为SSTable是不可变的,已删除数据的清除就转换成了对于过时的SSTable的垃圾回收。每个tablet的SSTables会注册在METADATA表中。Master服务器采用“标记-删除”的垃圾回收方式删除SSTable集合中废弃的SSTable。
最后,SSTable的不可变性使得我们可以快速分割tablet。我们让子tablets共享父tablet的SSTables,而不是为每个子tablet生成新的SSTables。{如果是这样的话,如前所述,一开始只有一个tablet,这样会不会导致SSTable的数目一直未变,只是它的大小一直在上升,但这样会导致它很难一次加载入内存,那么SSTable的分割又是何时发生的呢?}
你可能感兴趣的:(分布式与海量数据,Google,数据结构,正则表达式,应用服务器,网络应用)
《昼颜》里的日本女人:相遇要万种风情,分手要残忍绝情
迷影咖啡
作者:迷之菌子神奇菇迷影咖啡:一本正经做烘焙,胡说八道聊电影漫天萤火虫消散之时良宵就将过去,人们也说含苞待放的花蕾总会开了又谢,因紧紧相拥而面红耳赤的躯体,便是我们经历过这热爱的证明。夫妻关系介绍《昼颜》是2014年电视剧《昼颜:工作日下午三点的恋人们》的续集,故事发在电视剧情节结束的三年后,讲述了已经恢复独身的纱和偶然与曾经的出轨对象北野重逢后再次陷入感情漩涡的故事。《昼颜》制作灵感源自利佳子在
迎接2019
唯有杜康1994
告别2018这一年是机遇与挑战,痛苦与喜悦,失去与收获的一年一月:收获了第一份爱情,开始真正想去了解一个人三月:对工作有了更深入的认识,靠自己的力量完成晋升五月:搬家,住进了自己理想的公寓,一间属于自己的屋子。满地的书六月:外调广州,升经理,有了自己的第一个团队。七月:怀着自我否定,第一次完成了部门任务八月:第一个员工流失,痛哭不已明白无不散之筵席九月:员工陆续离开,经济是一切的根本。十月:陪员工
极狐GitLab 论坛 2.0 全新上线,可以在论坛上查找与 GitLab 相关的问题了~
极小狐
gitlab 极狐GitLab devops GitLab ci/cd devsecops SCM
安装出现依赖错误?版本升级搞不定?遇到422、500就懵逼了?不知道某个功能是免费or付费?……使用GitLab这种全球顶级的DevOps平台进行软件研发时,总会遇到一些困惑,想跟专业的技术人员快速交流以便获得答案,同时又想把这些问题沉淀下来以帮助他人?有这种赠人玫瑰,手有余香的解决方案吗?答案肯定有:论坛!!!论坛——一个各路大神聚集的地方,一个可以解惑答疑问道的地方。解惑:搜索与自己问题相同或
数据结构奇妙旅程之深入解析快速排序
山间漫步人生路
数据结构 排序算法 算法
快速排序(QuickSort)是一种高效的排序算法,它使用了分治法的策略来将一个数组排序。其基本思想是选择一个基准元素,通过一趟排序将待排序的数据分割成独立的两部分,其中一部分的所有数据都比基准元素小,另一部分的所有数据都比基准元素大,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。工作原理选择基准:从待排序的序列中选一个元素作为基准(pivo
我喝醉了,但是与你无关
Z先生的日记本
2019年04月10号晚上我和一个朋友喝酒了,彻彻底底的喝醉了,喝到短片,事后我问L,我说我喝醉了之后,都发生了什么,L没有告诉我详情,但是跟我说了大致,他说我跟他一直聊天,说自己小的时候的事,说自己爸妈的事,说自己现在过得很苦可能,确实是喝醉了酒,才会毫无防备的跟其他人说这些吧。L还说感觉我过得很苦,很心疼。醉了酒之后还哭了,想想还真是丢人一年前,在宿舍也有一瓶红酒,那是舍友出去拉赞助时候,友商
python抓包与解包_Python—网络抓包与解包(pcap、dpkt)
weixin_39691055
python抓包与解包
pcap安装[root@localhost~]#pipinstallpypcap抓包与解包#-*-coding:utf-8-*-importpcap,dpktimportre,threading,requests__black_ip=['103.224.249.123','203.66.1.212']#抓包:param1eth_name网卡名,如:eth0,eth3。param2p_type日志捕
拼多多纸巾推荐:品质与性价比的完美结合
氧惠帮朋友一起省
拼多多纸巾推荐拼多多纸巾返现怎么做在我们的日常生活中,纸巾已经成为不可或缺的用品。无论是在家庭、办公室还是旅途中,纸巾都是我们随时随地需要的物品。随着电商平台的兴起,越来越多的人选择在网上购买纸巾。其中,拼多多作为国内知名的电商平台之一,以其独特的社交电商模式和实惠的价格吸引了大量用户。今天,我们就来探讨如何在拼多多上选择品质优良、性价比高的纸巾,以及如何通过一些小技巧来获取更多的优惠。一、品质与
word字号和mathtype磅值关系及批量修改
小铁匠-Ma
office小技巧 经验分享
word字号和mathtype磅值关系及批量修改1.字号与磅值关系字号「八号」对应磅值5字号「七号」对应磅值5.5字号「小六」对应磅值6.5字号「六号」对应磅值7.5字号「小五」对应磅值9字号「五号」对应磅值10.5字号「小四」对应磅值12字号「四号」对应磅值14字号「小三」对应磅值15字号「三号」对应磅值16字号「小二」对应磅值18字号「二号」对应磅值22字号「小一」对应磅值24字号「一号」对应
美团自动配送车2024春季招聘 | 社招专场
美团技术团队
关于美团自动配送团队美团自动配送以自研L4级自动驾驶软硬件技术为核心,与美团即时零售业务结合,形成满足公开道路、校园、社区、工业园区等室外全场景下的自动配送整体解决方案。美团自动配送团队成立于2016年,团队成员来自于Waymo、Cruise、Pony.ai、泛亚等自动驾驶行业头部公司,自动驾驶技术团队博士占比高达30%,依靠视觉、激光等传感器,实时感知预测周围环境,通过高精地图定位和智能决策规划
php 把一个数组分成有n个元素的二维数组的算法
风清扬-独孤九剑
php php 算法
一、第一种解法0){$columns_map[$position]++;//这个地方格外注意,$position与$columns比较$position=($position<$columns-1)?++$position:0;$array_length--;}foreach($columns_mapas$val){$newarray[]=array_splice($array,0,$val);}
花气袭人知昼暖
柒侠传
花气袭人知昼暖高一七班黄韵熹37号花袭人,原名花珍珠,位列金陵十二钗又副册中的第二位。“袭人”这一称呼源于“花气袭人知昼暖”这一诗句,是宝玉给起的。想起来便觉得暖融融的,一如花袭人温柔的笑容。但花袭人着实是令人又爱又怕的角色。第二十一回的回目将她赞作“贤袭人”,脂砚斋在一旁批道“当得起”。花袭人对宝玉的确是一片真心。她为劝宝玉收敛他那成日在大观园里与姐姐妹妹“厮混”的性子,假借家人赎回的机会,软语
你之所以胖,可能是因为小时候发生这件事!还不赶快甩锅
周围_5d19
通常,我们认为,“肥胖”主要是由于饮食不节制、不经常运动等等因素引起的。但最近,我国学者开展的一项针对6到18岁儿童青少年、随访长达十年的代谢综合征研究结果,在权威国际期刊发表。研究发现,儿童的肥胖和超重与睡眠密切相关,儿童、青少年时期睡眠不好,成人后也更容易患心血管疾病。那么,为什么儿童青少年睡眠不足会导致肥胖呢?今天就带大家一探究竟。儿童青少年肥胖的现状如何?近日,一项刊载在医学权威期刊《柳叶
uni-app实现 步骤条
夏夏的码农
uni-app
实现如图样式html部分代码如下投资期限与收益0?'active':'default'">募集开始1?'active':'default'">募集结束2?'active':'default'">产品成立3?'active':'default'">产品到期0?'active-step1':'step1'">1?'active-st
【算法分析与设计】去除重复字母
五敷有你
算法分析与设计 java javascript 开发语言 算法 数据结构
个人主页:五敷有你系列专栏:算法分析与设计⛺️稳中求进,晒太阳题目给你一个字符串s,请你去除字符串中重复的字母,使得每个字母只出现一次。需保证返回结果的字典序最小(要求不能打乱其他字符的相对位置)。示例示例1:输入:s="bcabc"输出:"abc"示例2:输入:s="cbacdcbc"输出:"acdb"思路贪心+单调栈实现【字符串删除一个字符使其字典序最小的贪心策略】:对于两个长度相同的字符串,
购物返利平台是真的吗
返金app平台高佣返利省钱
购物返利平台是真实存在的,它们提供一种通过购物来获取一定比例返现的服务。这些平台通常与商家合作,通过返利链接或其他追踪方式来追踪用户的购物行为,然后将一部分返现金额返还给用户。然而,需要注意的是,并非所有的购物返利平台都是可信的。在选择使用购物返利平台时,建议您注意以下几个方面:可信度和口碑:查看平台的用户评价和口碑,了解其他用户对该平台的使用体验和返利情况。合作商家:了解平台的合作商家是否可靠,
<商务世界>《第25课 餐桌上的礼仪-简单的流程》
Ealser
商务世界 中国餐桌礼节
第一:迎客席座一般的程序是主人给客人邀请函——日子到了,主人到门外迎客——客人到了,问候几句——带着可人到0客厅小坐一会儿,给客人茶点——带客人入席坐好!第二:入座与座次首先要请客人中长者或地位高的先入座,再按身份地位依次入座,入座时要从椅子左边进入。(正对门口的为上座,一般是根据对方的.身份地位来安排)。入座后不要动筷子,更不要弄出什么响声来,也不要起身走动。如果有什么事要向主人打招呼!(做小辈
【美丽特色乡村】,景德镇马鞍岭村,
粒子飞翔
【美丽特色乡村】,景德镇马鞍岭村,就像是陶渊明笔下的山水田园,阡陌交通,精美的白房参差错落,碧绿透亮的河水从不远处的深涧里连绵不绝流入此地,滋养着土里。成群的白鸭悠闲地在河水里戏水,人与环境达成和谐的境界。借助三宝国际瓷谷建设的契机,马鞍岭村迎来了天翻地覆的沧桑巨变,此地以陶瓷文化为特色,融合原来生态资源,修复了水碓遗址、矿坑遗址等历史文化遗产,提升生态环境现状。同时,依托三宝溪围绕整个村落,对河
2019.11.28感恩日记
afab5b74f713
1.感谢真我守护,一觉到天明,谢谢谢谢谢谢!2.感谢一大早,橘子就甩来4800的大红包,谢谢谢谢谢谢!3.感谢今天代理宝宝们疯狂加单,钱宝宝流入小十万,太牛了你们,有你们真好,谢谢谢谢谢谢!4.感谢自己拥有钱宝宝,可以去群里给宝宝们发红包,表达我的爱,谢谢谢谢谢谢钱宝宝爱我!5.感谢自己的细胞宝宝们,让我保持健康与活力,可以自由活动,活力满满,谢谢谢谢谢谢!6.感谢芬姐甩来订单,谢谢谢谢谢谢钱宝宝
请简单介绍一下Shiro框架是什么?Shiro在Java安全领域的主要作用是什么?Shiro主要提供了哪些安全功能?
AaronWang94
shiro java java 安全 开发语言
请简单介绍一下Shiro框架是什么?Shiro框架是一个强大且灵活的开源安全框架,为Java应用程序提供了全面的安全解决方案。它主要用于身份验证、授权、加密和会话管理等功能,可以轻松地集成到任何JavaWeb应用程序中,并提供了易于理解和使用的API,使开发人员能够快速实现安全特性。Shiro的核心组件包括Subject、SecurityManager和Realms。Subject代表了当前与应用
谷歌浏览器驱动Chromedriver(114-120版本)文件以及驱动下载教程
pigerr杨
Python python chrome drivers
ChromeDriver官方网站GitHub||GoogleChromeLabs/chrome-for-testingChromeDriver113-125_JSONChromeforTestingavailability123-125zip白月黑羽Python基础|进阶|Qt图形界面|Django|自动化测试|性能测试|JS语言|JS前端|原理与安装
通俗易懂:什么是Java虚拟机(JVM)?它的主要作用是什么?
大龄下岗程序员
mysql java mysql spring
Java虚拟机(JavaVirtualMachine,JVM)是一种软件实现的抽象计算机,它负责执行Java字节码(Bytecode)。Java程序并不是直接在物理计算机上运行,而是先由Java编译器将源代码编译成与平台无关的字节码,然后由JVM负责读取字节码并在实际硬件架构上运行。JVM的主要作用包括以下几个方面:1.跨平台性-JVM是Java语言“一次编写,到处运行”(WriteOnce,Ru
虚拟 DOM 的优缺点有哪些
咕噜签名分发
前端 javascript 开发语言
虚拟DOM(VirtualDOM)技术作为现代前端开发中的重要组成部分,已经成为了众多流行前端框架的核心特性。它的引入为前端开发带来了诸多优势,同时也需要我们认真思考其潜在的考量。下面简单的介绍一下虚拟DOM技术的优势与缺点,深入探讨其在实际应用中的影响。提升性能虚拟DOM的最大优势之一是提升页面性能。通过比较前后两次虚拟DOM树的差异,最小化实际DOM操作,从而减少页面重渲染时的性能消耗。这种优
3、JavaWeb-Ajax/Axios-前端工程化-Element
所谓远行Misnearch
# JavaWeb 前端 ajax elementui java 前端框架
P34Ajax介绍Ajax:AsynchroousJavaScriptAndXML,异步的JS和XMLJS网页动作,XML一种标记语言,存储数据,作用:数据交换:通过Ajax给服务器发送请求,并获取服务器响应的数据异步交互:在不重新加载整个页面的情况下,与服务器交换数据并实现更新部分网页的技术,例如:搜索联想、用户名是否可用的校验等等。同步与异步:同步:服务器在处理中客户端要处于等待状态,输入域名
OpenCV 如何使用 XML 和 YAML 文件的文件输入和输出
愚梦者
深度学习 人工智能 计算机视觉 c++ opencv
返回:OpenCV系列文章目录(持续更新中......)上一篇:如何利用OpenCV4.9离散傅里叶变换下一篇:目标本文内容主要介绍:如何使用YAML或XML文件打印和读取文件和OpenCV的文本条目?如何对OpenCV数据结构做同样的事情?如何为您的数据结构执行此操作?使用OpenCV数据结构,例如cv::FileStorage,cv::FileNodeorcv::FileNodeIterato
docker基础(一)
运维搬运工
容器-docker docker 容器 运维
相关概念介绍Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖到一个可移植的容器中,然后发布到任何流行的linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,互相之间不会有任何接口。Docker有几个重要概念:dockerfile,配置文件,用来生成dockerimagedockerimage,交付部署的最小单元docker命令与API,定义命令与接口,支持第三方系统集
Golang标准库fmt深入解析与应用技巧
walkskyer
golang标准库 golang java 数据库
Golang标准库fmt深入解析与应用技巧前言fmt包的基本使用打印与格式化输出函数Print系列函数格式化字符串格式化输入函数小结字符串格式化基本类型的格式化输出自定义类型的格式化输出控制格式化输出的宽度和精度小结错误处理与fmt使用fmt.Errorf生成错误信息fmt包与错误处理的最佳实践小结日志记录与fmtfmt包在日志记录中的应用结合log包使用fmt进行高级日志处理小结fmt与IOfm
Flutter运行flutter doctor 命令长时间未响应如何解决
咕噜签名分发-淼淼
flutter
Hello大家好!我是咕噜铁蛋!在移动应用开发领域,Flutter以其高效、跨平台的特性吸引了众多开发者的关注。然而,在使用Flutter进行项目开发时,开发者可能会遇到各种问题,其中之一就是运行flutterdoctor命令时长时间未响应。今天铁蛋将深入探讨这一问题的成因、解决方案以及相关的Flutter环境配置知识。一、Flutter与flutterdoctor命令简介Flutter是Goog
桃李春风一杯酒
行走的石头521
桃李春风一杯酒,江湖夜雨十年灯。回眸处,雾霭沉沉。跌宕的现世里,与自己和解,不计较,不解释,不纠结,不凑合,读书品茗,赏花听雨,也不失为一种富足与自由。非常喜欢这段话,可能是最近桃花朵朵开的缘故吧!让我不由得想起了那些诗词里的桃花:1、桃花春水生,白石今出没。摇萝枝,半摇青天月。——李白《忆秋浦桃花旧游》2、桃花潭水深千尺,不及汪伦送我情!——李白《赠汪伦》3、黄雀始欲衔花来,君家种桃花未开。长安
唯品会优惠券与代金券:如何免费领取并巧妙使用?
氧惠全网优惠
在互联网购物日益盛行的今天,各类电商平台纷纷推出各种优惠活动,以吸引消费者。其中,优惠券和代金券是消费者最为喜爱的促销方式之一。唯品会,作为国内知名的折扣电商平台,也经常推出各种优惠券和代金券,让消费者在享受购物乐趣的同时,还能节省不少钱。那么,唯品会优惠券和代金券该如何免费领取,又该如何巧妙使用呢?一、唯品会优惠券与代金券的区别在探讨如何领取和使用之前,我们首先需要了解唯品会优惠券和代金券的区别
网络安全(黑客)——自学2024
小言同学喜欢挖漏洞
web安全 安全 网络 学习 网络安全 信息安全 渗透测试
01什么是网络安全网络安全可以基于攻击和防御视角来分类,我们经常听到的“红队”、“渗透测试”等就是研究攻击技术,而“蓝队”、“安全运营”、“安全运维”则研究防御技术。无论网络、Web、移动、桌面、云等哪个领域,都有攻与防两面性,例如Web安全技术,既有Web渗透,也有Web防御技术(WAF)。作为一个合格的网络安全工程师,应该做到攻守兼备,毕竟知己知彼,才能百战百胜。02怎样规划网络安全如果你是一
Enum 枚举
120153216
enum 枚举
原文地址:http://www.cnblogs.com/Kavlez/p/4268601.html Enumeration
于Java 1.5增加的enum type...enum type是由一组固定的常量组成的类型,比如四个季节、扑克花色。在出现enum type之前,通常用一组int常量表示枚举类型。比如这样:
public static final int APPLE_FUJI = 0
Java8简明教程
bijian1013
java jdk1.8
Java 8已于2014年3月18日正式发布了,新版本带来了诸多改进,包括Lambda表达式、Streams、日期时间API等等。本文就带你领略Java 8的全新特性。
一.允许在接口中有默认方法实现
Java 8 允许我们使用default关键字,为接口声明添
Oracle表维护 快速备份删除数据
cuisuqiang
oracle 索引 快速 备份 删除
我知道oracle表分区,不过那是数据库设计阶段的事情,目前是远水解不了近渴。
当前的数据库表,要求保留一个月数据,且表存在大量录入更新,不存在程序删除。
为了解决频繁查询和更新的瓶颈,我在oracle内根据需要创建了索引。但是随着数据量的增加,一个半月数据就要超千万,此时就算有索引,对高并发的查询和更新来说,让然有所拖累。
为了解决这个问题,我一般一个月会进行一次数据库维护,主要工作就是备
java多态内存分析
麦田的设计者
java 内存分析 多态原理 接口和抽象类
“ 时针如果可以回头,熟悉那张脸,重温嬉戏这乐园,墙壁的松脱涂鸦已经褪色才明白存在的价值归于记忆。街角小店尚存在吗?这大时代会不会牵挂,过去现在花开怎么会等待。
但有种意外不管痛不痛都有伤害,光阴远远离开,那笑声徘徊与脑海。但这一秒可笑不再可爱,当天心
Xshell实现Windows上传文件到Linux主机
被触发
windows
经常有这样的需求,我们在Windows下载的软件包,如何上传到远程Linux主机上?还有如何从Linux主机下载软件包到Windows下;之前我的做法现在看来好笨好繁琐,不过也达到了目的,笨人有本方法嘛;
我是怎么操作的:
1、打开一台本地Linux虚拟机,使用mount 挂载Windows的共享文件夹到Linux上,然后拷贝数据到Linux虚拟机里面;(经常第一步都不顺利,无法挂载Windo
类的加载ClassLoader
肆无忌惮_
ClassLoader
类加载器ClassLoader是用来将java的类加载到虚拟机中,类加载器负责读取class字节文件到内存中,并将它转为Class的对象(类对象),通过此实例的 newInstance()方法就可以创建出该类的一个对象。
其中重要的方法为findClass(String name)。
如何写一个自己的类加载器呢?
首先写一个便于测试的类Student
html5写的玫瑰花
知了ing
html5
<html>
<head>
<title>I Love You!</title>
<meta charset="utf-8" />
</head>
<body>
<canvas id="c"></canvas>
google的ConcurrentLinkedHashmap源代码解析
矮蛋蛋
LRU
原文地址:
http://janeky.iteye.com/blog/1534352
简述
ConcurrentLinkedHashMap 是google团队提供的一个容器。它有什么用呢?其实它本身是对
ConcurrentHashMap的封装,可以用来实现一个基于LRU策略的缓存。详细介绍可以参见
http://code.google.com/p/concurrentlinke
webservice获取访问服务的ip地址
alleni123
webservice
1. 首先注入javax.xml.ws.WebServiceContext,
@Resource
private WebServiceContext context;
2. 在方法中获取交换请求的对象。
javax.xml.ws.handler.MessageContext mc=context.getMessageContext();
com.sun.net.http
菜鸟的java基础提升之道——————>是否值得拥有
百合不是茶
1,c++,java是面向对象编程的语言,将万事万物都看成是对象;java做一件事情关注的是人物,java是c++继承过来的,java没有直接更改地址的权限但是可以通过引用来传值操作地址,java也没有c++中繁琐的操作,java以其优越的可移植型,平台的安全型,高效性赢得了广泛的认同,全世界越来越多的人去学习java,我也是其中的一员
java组成:
通过修改Linux服务自动启动指定应用程序
bijian1013
linux
Linux中修改系统服务的命令是chkconfig (check config),命令的详细解释如下: chkconfig
功能说明:检查,设置系统的各种服务。
语 法:chkconfig [ -- add][ -- del][ -- list][系统服务] 或 chkconfig [ -- level <</SPAN>
spring拦截器的一个简单实例
bijian1013
java spring 拦截器 Interceptor
Purview接口
package aop;
public interface Purview {
void checkLogin();
}
Purview接口的实现类PurviesImpl.java
package aop;
public class PurviewImpl implements Purview {
public void check
[Velocity二]自定义Velocity指令
bit1129
velocity
什么是Velocity指令
在Velocity中,#set,#if, #foreach, #elseif, #parse等,以#开头的称之为指令,Velocity内置的这些指令可以用来做赋值,条件判断,循环控制等脚本语言必备的逻辑控制等语句,Velocity的指令是可扩展的,即用户可以根据实际的需要自定义Velocity指令
自定义指令(Directive)的一般步骤
&nbs
【Hive十】Programming Hive学习笔记
bit1129
programming
第二章 Getting Started
1.Hive最大的局限性是什么?一是不支持行级别的增删改(insert, delete, update)二是查询性能非常差(基于Hadoop MapReduce),不适合延迟小的交互式任务三是不支持事务2. Hive MetaStore是干什么的?Hive persists table schemas and other system metadata.
nginx有选择性进行限制
ronin47
nginx 动静 限制
http {
limit_conn_zone $binary_remote_addr zone=addr:10m;
limit_req_zone $binary_remote_addr zone=one:10m rate=5r/s;...
server {...
location ~.*\.(gif|png|css|js|icon)$ {
java-4.-在二元树中找出和为某一值的所有路径 .
bylijinnan
java
/*
* 0.use a TwoWayLinkedList to store the path.when the node can't be path,you should/can delete it.
* 1.curSum==exceptedSum:if the lastNode is TreeNode,printPath();delete the node otherwise
Netty学习笔记
bylijinnan
java netty
本文是阅读以下两篇文章时:
http://seeallhearall.blogspot.com/2012/05/netty-tutorial-part-1-introduction-to.html
http://seeallhearall.blogspot.com/2012/06/netty-tutorial-part-15-on-channel.html
我的一些笔记
===
js获取项目路径
cngolon
js
//js获取项目根路径,如: http://localhost:8083/uimcardprj
function getRootPath(){
//获取当前网址,如: http://localhost:8083/uimcardprj/share/meun.jsp
var curWwwPath=window.document.locati
oracle 的性能优化
cuishikuan
oracle SQL Server
在网上搜索了一些Oracle性能优化的文章,为了更加深层次的巩固[边写边记],也为了可以随时查看,所以发表这篇文章。
1.ORACLE采用自下而上的顺序解析WHERE子句,根据这个原理,表之间的连接必须写在其他WHERE条件之前,那些可以过滤掉最大数量记录的条件必须写在WHERE子句的末尾。(这点本人曾经做过实例验证过,的确如此哦!
Shell变量和数组使用详解
daizj
linux shell 变量 数组
Shell 变量
定义变量时,变量名不加美元符号($,PHP语言中变量需要),如:
your_name="w3cschool.cc"
注意,变量名和等号之间不能有空格,这可能和你熟悉的所有编程语言都不一样。同时,变量名的命名须遵循如下规则:
首个字符必须为字母(a-z,A-Z)。
中间不能有空格,可以使用下划线(_)。
不能使用标点符号。
不能使用ba
编程中的一些概念,KISS、DRY、MVC、OOP、REST
dcj3sjt126com
REST
KISS、DRY、MVC、OOP、REST (1)KISS是指Keep It Simple,Stupid(摘自wikipedia),指设计时要坚持简约原则,避免不必要的复杂化。 (2)DRY是指Don't Repeat Yourself(摘自wikipedia),特指在程序设计以及计算中避免重复代码,因为这样会降低灵活性、简洁性,并且可能导致代码之间的矛盾。 (3)OOP 即Object-Orie
[Android]设置Activity为全屏显示的两种方法
dcj3sjt126com
Activity
1. 方法1:AndroidManifest.xml 里,Activity的 android:theme 指定为" @android:style/Theme.NoTitleBar.Fullscreen" 示例: <application
solrcloud 部署方式比较
eksliang
solrCloud
solrcloud 的部署其实有两种方式可选,那么我们在实践开发中应该怎样选择呢? 第一种:当启动solr服务器时,内嵌的启动一个Zookeeper服务器,然后将这些内嵌的Zookeeper服务器组成一个集群。 第二种:将Zookeeper服务器独立的配置一个集群,然后将solr交给Zookeeper进行管理
谈谈第一种:每启动一个solr服务器就内嵌的启动一个Zoo
Java synchronized关键字详解
gqdy365
synchronized
转载自:http://www.cnblogs.com/mengdd/archive/2013/02/16/2913806.html
多线程的同步机制对资源进行加锁,使得在同一个时间,只有一个线程可以进行操作,同步用以解决多个线程同时访问时可能出现的问题。
同步机制可以使用synchronized关键字实现。
当synchronized关键字修饰一个方法的时候,该方法叫做同步方法。
当s
js实现登录时记住用户名
hw1287789687
记住我 记住密码 cookie 记住用户名 记住账号
在页面中如何获取cookie值呢?
如果是JSP的话,可以通过servlet的对象request 获取cookie,可以
参考:http://hw1287789687.iteye.com/blog/2050040
如果要求登录页面是html呢?html页面中如何获取cookie呢?
直接上代码了
页面:loginInput.html
代码:
<!DOCTYPE html PUB
开发者必备的 Chrome 扩展
justjavac
chrome
Firebug:不用多介绍了吧https://chrome.google.com/webstore/detail/bmagokdooijbeehmkpknfglimnifench
ChromeSnifferPlus:Chrome 探测器,可以探测正在使用的开源软件或者 js 类库https://chrome.google.com/webstore/detail/chrome-sniffer-pl
算法机试题
李亚飞
java 算法 机试题
在面试机试时,遇到一个算法题,当时没能写出来,最后是同学帮忙解决的。
这道题大致意思是:输入一个数,比如4,。这时会输出:
&n
正确配置Linux系统ulimit值
字符串
ulimit
在Linux下面部 署应用的时候,有时候会遇上Socket/File: Can’t open so many files的问题;这个值也会影响服务器的最大并发数,其实Linux是有文件句柄限制的,而且Linux默认不是很高,一般都是1024,生产服务器用 其实很容易就达到这个数量。下面说的是,如何通过正解配置来改正这个系统默认值。因为这个问题是我配置Nginx+php5时遇到了,所以我将这篇归纳进
hibernate调用返回游标的存储过程
Supanccy2013
java DAO oracle Hibernate jdbc
注:原创作品,转载请注明出处。
上篇博文介绍的是hibernate调用返回单值的存储过程,本片博文说的是hibernate调用返回游标的存储过程。
此此扁博文的存储过程的功能相当于是jdbc调用select 的作用。
1,创建oracle中的包,并在该包中创建的游标类型。
---创建oracle的程
Spring 4.2新特性-更简单的Application Event
wiselyman
application
1.1 Application Event
Spring 4.1的写法请参考10点睛Spring4.1-Application Event
请对比10点睛Spring4.1-Application Event
使用一个@EventListener取代了实现ApplicationListener接口,使耦合度降低;
1.2 示例
包依赖
<p