CrazyAirhead

疯狂的傻瓜,傻瓜也疯狂——傻方能执著,疯狂才专注!

0%

以下内容是极客时间《技术与商业案例解读》专栏的摘录,本专栏由徐飞博士撰写。可以订购该专栏阅读更多精彩解读,开拓眼界,了解互联网发展历史和创业经验。

SAP 是总部位于德国的全球最大的 ERP 公司。作为一家重量级的企业应用软件公司,SAP 曾经有过一段风光的日子。

但是而后的日子也开始不好过起来。

日子不好过的主要原因是 SAP 的软件需要跑在数据库上,而备选的数据库一般来说不是 IBM 的 DB2,就是 Oracle。本来两者和 SAP 的软件配合,相得益彰,曾经一度合作得很愉快。但随着 Oracle 开始进军企业级软件市场,把手伸到 SAP 的地盘来,SAP 的日子就开始不好过起来。

Oracle 在 21 世纪初进行了一系列的并购,包括收购了 Siebel 和仁科等重要的企业级软件企业,把自己从底层数据库到企业级软件的体系补全了。这样一来,SAP 就麻烦了,因为自己的软件依赖于对方的数据库,而对方却还能够提供类似的企业级软件。

好在还有一个 IBM 的 DB2 可以用。SAP 一度和 IBM 合作,希望两者的结合可以给自己带来所谓的强强联合。但是 IBM 的 DB2 却一直面临着诸多问题,比如本身就不是市场上最好的数据库,人才流失又很严重。所谓的合作开展起来,效果却非常有限。

在这个背景下,SAP 开展了一场技术与忽悠并存的战略大跃进,也就是 SAP 著名的 HANA 战略。HANA 的出现对 SAP 和业界都产生了巨大的影响。其实施的过程可谓精彩绝伦,堪称一部大制作的“影片”。

今天我就来讲一讲这个 SAP 的 HANA 战略。

让我们先把时间倒回到 2009 年。这一年,数据库的两大顶级会议之一的 SIGMOD 在罗德岛召开。我最后一次以 PhD 的身份参加 SIGMOD,所以对这个会议印象深刻。这种会议一般都会有赞助商。出钱多的金主很多时候会给一个 Keynote 的讲座。

2009 年的金主是 SAP。这多少有点让人大跌眼镜。一个做企业级软件的公司,来一个数据库顶级会议上大把撒钱,怎么看怎么怪。

在这次大会上,SAP 董事会主席兼创始人之一的哈索·普拉特纳(Hasso Plattner)给了这样一个 Keynote:A Common Database Approach for OLTP and OLAP Using an In-memory Column Database。这个 Keynote 宣告了 SAP 要搞一个内存数据库,它的名字叫 HANA。

SAP 要搞数据库,这可是一件大事情。一个做应用软件的要进军数据库市场,说明“兔子急了要咬人”了。但是企业级软件毕竟是应用软件,而数据库是基础架构软件。就像一个“做菜高手”突然说要开始“杀鸡”,先不说对方哪里来的底气,最起码外界对这个“做菜高手”的看法,肯定是见仁见智的。

HANA 是 High-Performance Analytic Appliance 的简称。SAP 要做的这个数据库,作为一个“做菜高手”进军“杀鸡市场”的第一炮,打得很响亮。按照 SAP 的宣传,它有着市面上传统的数据库很多不具备的特性。

下面我们可以一起了解一下这些特性,这很有必要。
第一,HANA 选择了按列存储的同时支持事务处理。传统数据库是按行存储的,数据仓库近些年来才开始按照列式存储。按行存储对事务处理方便,但是不利于分析处理;按列存储则相反。但是这两者的不利于程度是有所不同的。

通常来说,一个数据库如果同时支持事务处理和分析处理,那么数据库厂商会选择按行存储,因为按列存储的同时支持高效率的事务处理是非常难的。但是 HANA 却选择了按列存储的同时还支持事务处理,这个用数据库界“老司机”的话来说就是,要么是艺高人胆大,要么是无知者无畏。

第二,做出把所有的数据都放在内存里这个假设。今天来看,内存不是很贵了,但是在 2009 年敢做出那样的假设胆子就不是一般的大了。一个数据库一旦数据都在内存里,很多传统数据库的基本假设就都不一样了,做法当然也就很不一样。

所以 HANA 在很多演示的时候,查询极快。一个在 Oracle 或者 DB2 上需要跑一天才能做出来的报表查询,在 HANA 那儿 3 秒钟搞定。对,就是这么快。当然,其实查询是精心挑选的,能够存储这么多数据的机器的配置是非常高的。

第三,因为 HANA 选择了在一个系统同时支持事务处理和分析查询,这就让 HANA 的数据不需要额外 ETL,企业也不需要为分析查询专门配备另外一份列存的数据。某种程度上,HANA 宣称自己节省了企业的消耗,也是对的。而且因为两者共享数据,分析查询的时候能够查询的数据就非常新了。这对企业来说也是非常有必要的。

第四,HANA 几乎完整地整合了 R 的功能,并且把 SAP 业务相关的很多功能直接在 HANA 内部实现了。这有点反计算机软件构架里面的封装。然而在内存数据库的环境下让数据离业务相关计算更近,无疑是一种效率上极其有效的策略。

第五,HANA 采用了现代数据库里常用的 Shared-nothing 的体系架构。这种体系架构数据被纵向按照某个主键切分,每台机器只需要负责自己的部分。这让 HANA 具备了非常灵活的资源配置,而且加了机器查询也就会变得更快,立竿见影。简而言之,HANA 的体系架构很新。

综上所述,HANA 在技术上是很有创新的,而且单纯从 SAP 公布出来的这些技术细节来看,HANA 的确是具备了在很多方面对传统数据库发起挑战的能力。所以,一个“做菜”的,看起来“杀鸡”也杀得很漂亮。很多人不得不为 SAP 精彩的 HANA 数据库疯狂打 Call 了。

由于 SAP 的这个举措,首先受到伤害的是和 SAP 合作的 IBM 的 DB2 组了。毕竟,本来是难兄难弟抱团取暖,现在变成了一个人冲锋陷阵,抛弃了老伙伴。

其次受到威胁的当然是那个坐在数据库领域第一把交椅上的 Oracle。试想一下,原来用 SAP 的必须上 Oracle,而用 Oracle 的还可以搭自己家里的企业级软件。这让 Oracle 处于多有利的地位呀!但突然之间局势就变了,SAP 有自己的数据库了,而且还很快、很厉害、很先进。接下来 Oracle 的这个生意就不好做了。

但是对 2009 年的 SAP 来说,HANA 这个吸引眼球的宣传,一下子让原本已经成为或者即将成为二流公司的 SAP 回到了聚光灯前,不管产品有没有做出来,最起码先把风头抢占了。SAP 公司 HANA 战略的实施,当得上商业教科书的经典案例。对于一个 2009 年就吹起来的、但是却没有实际产品的 HANA 数据库,SAP 的开发和商业化道路概括来说就是四个字:心黑胆肥。

2010 年开始,SAP 在大力宣传 HANA 的时候,并没有大规模地卖 HANA,而是非常有重点地挑了几个人傻钱多的企业开始做内测。这些企业不但钱多,而且还愿意当小白鼠。2011 年以后,HANA 面向的对象稍微多了一点,但主要还是非常有钱的大型企业,比如德国电信、中石油、中石化这种。可以说一般没钱的企业是享受不到充当 HANA 小白鼠资格的。

HANA 需要内存 64 GB 以上的机器,但是一般来说 64 GB 跑起来大数据还是不够快。所以通常需要更多的钱买非常贵的硬件。而 HANA 的软件的最低配置是 30 万美元起。所以软硬件一起更是耗资巨大。从 2011 年到 2014 年,SAP 一直对 HANA 相关的产品定以非常高的价格。基本上这个产品给人的感觉就是:只有有钱的公司才能用得起,没钱的就算了。

所以市面上对 HANA 的各种抱怨,主要都集中在了 HANA 高昂的价格上了。然而这其实也是 SAP 想要的。
• 一方面,SAP 的高价让大家把对 HANA 的关注都集中到了价格上;
• 另外一方面,SAP 通过高价获得了不少优质客户和源源不断的金钱,更是从这个高价的过程里获得了对产品来说非常重要的形象问题:HANA 就是“高大上”的代表。

另外,因为价格高,所以实际上真正使用 HANA 的用户并不多,而且这些用户的硬件多半都是高配版。这样,HANA 即使有这样或那样的问题,暴露在大众面前的机会也不多。所以在收获金钱的同时,SAP 也给 HANA 的逐步完善赢得了很多的时间。

SAP 宣传的大胆还体现在对 HANA 的宣传上。SAP 宣传 HANA 的时候,把 HANA 和 Oracle 的产品做对比。SAP 表示,HANA 是基于最新硬件和研究的新一代数据库,代表着数据库的未来;而 Oracle 则是一个已经存在了很多年的老朽的东西,不代表未来。

这个宣传,我们先不管是不是言过其实,但它的实际效果的确是非常好。那些不差钱的企业,比如中国石油,要的就是最新、最贵的东西。于是世界各地大量有钱的企业排队从 Oracle 转到 HANA 上。这些企业有中国的,有日本的,还有欧洲、美洲的。很多企业都是被 HANA 这种舍我其谁的势态给吸引过来的。

说起来真的是一物降一物。这么多年来,HANA 的出现,第一次对 Oracle 的基本盘产生了动摇。在这之前不管是 DB2 还是 SQL Server,Oracle 都不屑一顾。在 Oracle 看来,那些无非是跟在后面吃点“残羹冷炙”,算不得威胁。而 HANA 不断抢占 Oracle 的用户,让 Oracle 也开始着急起来。Oracle 在商业上显得非常被动。

并且后续 Oracle 一系列的发布:从 Timesten、Exalytics、Exadata 到 Oracle 12c In-Memory Option,简直是用实践再次证明了自己就是 HANA 的一个追随者,而 SAP 才是内存数据库的开拓者。所以很多人更懒得去理会那个亦步亦趋的 Oracle 了。Oracle 慌了,可能 Oracle 也没有想到,自己当初抢占 SAP 领地,SAP 这次也同样还回来了。

SAP 宣传 HANA 的另外一个十分胆大的地方就是敢吹,什么都敢吹。每次都是新功能、新特性先做一个半成品,就发布出去给客户用。不但发布出去,还在客户文档里面大肆吹多牛多牛。而实际上呢?这些半成品的 Bug 一堆又一堆。举个例子,HANA 在 2011 年的时候连 High availability 都还不具备,居然就开吹 HANA 不需要 High availability。然后用户们竟然还真的信了。

当然仅仅靠吹,牛皮总会有吹破的时候。所以 SAP 对 HANA 的商业实施的另外一举措就是疯狂地开发和发布新版本。在 SAP 把 HANA 推出市场以后,基本上开发团队做到了半个月到一个月一个新版本。每次新版本都会增加很多半成品的新功能,与此同时,也把前面几个版本里大的 Bug 都修复好。

这个做法的好处是:一方面,用户当了小白鼠测试了新功能,减少了自己投入在测试上面的成本;另外一方面,修复得如此及时,用户体验非常好。客观一点说,4 年发布了 80 个新版本,而且每两个版本之间的差异还是很大的,也就是说半年后和半年前的 HANA,简直就不是同一个软件。这是非常不容易且难得的高效率开发。

不仅如此,SAP 还在公司内部把 HANA 作为公司战略高度的产品来推广。具体来说,销售部门卖产品的业绩要重点看 HANA 卖了多少。开发团队各个产品组的新功能必须先支持 HANA 才可以去开发。至于没有 HANA 能不能跑起来,就不是必要条件了。总之,从宣传到销售到市场到研发一切以支持 HANA 为最高优先级。SAP 在那几年里,一直处于这样一种全力以赴的状态。

当然 SAP 清楚地知道自己很“跛脚”:传统数据库相关的技术积累太过薄弱,所以 SAP 在大张旗鼓开发 HANA 的同时,做的另外一件偷偷摸摸的事情是收购一个数据库厂商。SAP 买下了日子不好过的老牌数据库公司 Sybase。Sybase 虽然这些年产品卖得不好,但是在数据库领域还是有数十年积累的。这些传统数据库的技术,对 SAP 就非常地重要。

获得了 Sybase 的技术支持以后,SAP HANA 的体系立刻变得完整起来。举个例子,以前是所有数据全部在内存里才能用,但是总有人不是土豪,没那么有钱,买不起太高端大内存的机器,怎么办?HANA 后期的完整解决方案里面就有 cold data 存磁盘的办法,当然用的是 Sybase 那儿买的技术。

另外一个特别重要的是实时备份技术,这在任何商用数据库里都很成熟,但是 HANA 一直是“裸奔”的。买了 Sybase 后,就迅速地集成了 Sybase Replication Server。

SAP 偷偷地收购 Sybase,绝对是 SAP 下的一盘大棋里关键而又冒险的一步。成功了,一下子就获得了 Sybase 的技术,从而弥补了 SAP 的先天不足;失败了,HANA 的各种缺陷迟早会暴露出来的。那时 SAP 就会比较难往前走了。

Sybase 到手,关键技术整合起来后,2015 年的 HANA 已经是一个各方面都非常领先的内存数据库,即便是 Oracle 这样的“大佬”也无法有任何的实力可以撼动了。这样一来 SAP 的战略转型就顺理成章了。

对 SAP 来说,有和没有 HANA 是生死攸关的。HANA 战略的成功,无疑是技术和商业上的同时成功。这样的成功称得上是商业教科书的经典案例。

SAP HANA 的故事精彩到可以拍成电影。SAP 的 HANA 战略很成功,徐飞老师说成功的忽悠和成功的执行,就是一个成功的产品,想知道老师是如何总结的,扫码订购该专栏。

最近在微博中看了这个视频。刚好呢,自己练习左手使用筷子三个来月了,对于正确使用筷子算是有一些体验可以分享一下。

在李笑来老师的得到专栏《通往财富自由之路》里中一篇讲关于“学习能力”这个概念的文章,文章中拿了使用筷子做例子,我也是使用这种方式来练习左手用筷子的,所以先引用下该文章内容:

“学会如何正确使用筷子”,其实还真的是个好例子值得反复审视。

现在有两种情况:

  • 你自己知道自己确实不会用筷子;
  • 你自己知道自己能正确用筷子……

若你自己不会用筷子,接下来你要看看自己有没有能力达到学习能力进阶的第二个阶段:通过读书、读教程,学会一项技能;如果你自己确定自己能够正确地使用筷子,那你现在可以尝试再进阶半步:看看自己有没有能力教会别人正确地使用筷子……

我在网上翻了翻,写得最好的教程,居然(其实也很自然)是老外写的,在WikiHow上:

https://www.wikihow.com/Eat-with-Chopsticks

有文字讲解,也有视频示范。先去看看,看看你自己能不能学会?或者想象一下,若是你教别人(比如自己的孩子用筷子),你应该如何教?最重要的关键在哪里?为什么看起来这么简单的事儿能难住2/3以上的人群?

我们总说:屁股决定脑袋。

你所在的位置会决定你看问题的角度,以及应对的方式。对于同一个问题,改变了位置之后,可能看法会截然不同,甚至能够找到更优质的解决方法。

面对“学习”这件事的时候,这句话同样适用。

如果你总是以一个“学生”去要求自己,其实无意间降低了自己的标准。因为你的目标只是学会,或者看似学会。但实际上检验一个人是否真正掌握了一项技能的最好方法,就是让他把这个技能教给别人。

所以如果大家在学习的过程中,脑子里始终想着未来要把它教给其他人,那么对于自己的要求自然会提高,同时我们的学习效率和效果自然也会更好。

这么多年来,我经常拿这事儿当例子,用来证明:

有很多事情,即便是非常简单,都有可能难住一些人一辈子;

这件事儿还能证明:

这么简单的事儿,绝大多数人竟然不会教,甚至连自己的孩子都教不会……只顾着最后在那里发脾气,而后无可奈何……
如果能够仔细观察、最终找到重点的话,基本上是教的人两分种就讲明白,而后学的人五分钟之内就能搞定,随后摆脱一辈子的尴尬的事情。

正确使用筷子

关键之处其实有以下这么两点:

  • 两根筷子中,下面那根一直是处于静止状态的;
  • 张开、夹上的动作,其实来自于上面那一根;
    最为关键的是,如何令下面那根处于稳定状态呢?
  • 下面那根筷子,跟手一共有三个接触点:两端作为支点;
  • 大姆指的根部在中间压住筷子,无名指其实是“反向用力顶住”……
  • 大多数人败在无名指的用力方向上,这个方向搞对了,下面那根筷子就稳定了;
  • 接下来就是练习几分种如何用大姆指和食指控制上面那根筷子并夹住东西……
  • 反复练习,从笨拙到熟练的过程,本质上来看是大脑在建立沟回的过程。

那些之前就会用筷子的人,不妨对比一下,你教的方法、路径、重点,和我的一样吗?不一样的话,比我的更有效吗?如果比我的更有效不妨教教我,我也想有机会提高效率。许多年来,我在教别人如何学习的过程中,顺带帮助很多很多成年人“突然之间开始能够正确熟练地使用筷子这个神奇的东西……”。

当时也不太以为意,只是明确的知道自己的方式是不一样的,表现为下面的那个筷子是用无名指顶住的,而不是中指,上面的筷子是用中指和食指及大姆指夹住的(有点像抓笔),其他方面基本就一样了。效率上是否有优势就不得而知了。另外呢,这篇文章的评论里不少人说改正了自己多年的不正确的方式,或者学会了左手(或右手)用筷子,总之觉得是有用的。

直到这学期署假,儿子幼儿园要求开始教小孩使用筷子时,我才重视起来。儿子是左利手,用匙子和笔都是用左手,用筷子自然也是左手。教小孩呢,我觉得最好的方式是就示范,但我用右手,在示范时儿子还是不太懂。然后呢,我就开始在中午吃饭的时候练习起了左手用筷子,用的就是上面教的方法。这篇文章是2017年6月发布的,而自己真正开始实践已经是一年多过去了,想想真是刚需决定行动力。

下面说说自己的体验。

刚开始呢,确实很容易就能掌握手抓筷子的方式,比如很容易你就能夹起黄豆或者花生之类的东西。

接下来发现夹米饭时,上面的筷子很容易和下面的筷子错开,而不能夹稳,此时右手就会想去帮忙,或者说右手的食指就感觉在动一样。你或许听说过,为了帮助左手受伤的人恢复需要把右手绑起来,所以自己逐步通过固定手在桌子上或者揣在口袋里来克服。

食物总是多种多样,左手用筷子时发现碰到一些比较大的食物(比如红烧肉)时,就张不开,夹不起来。一开始比较粗暴一点,直接用一只筷子插进去。大致练习左手两个月之后,又点了一次红烧肉,突然想能不能用自己右手的方式呢,因为自己右手用了三个手指控制能张得比较开。可是发现居然不能很快的换一种方式,就像左手只记住了上面的方法,用另一种方式就很难,或者总是想换到之前的那种。我是大学时因为和同学一起玩夹花生米的游戏对自己的夹法有所改进的,之前是什么模样,竟然没有多少印象了。之后换了回来,发现无名指往上用力的体会也会深一些,确实能减少上下筷子错开。

左手用了一段时间了,中指顶住筷子的地方还是会疼,是的,你可曾想起刚开始学自行车时会紧紧的抓住车把,就想把他拽下来一样。

应该是还需要时间,还需要练习,反复练习,从笨拙到熟练的过程,本质上来看是大脑在建立沟回的过程。之前评论中回复学会正确使用筷子的人有多少是真正在使用并从中获益呢,或许只有他们自己知道了。但对于我自己来说,要教会儿子正确使用筷子我是绝对有信心了。

If you want to test the HBase Indexer with a higher throughput than the manual puts explained in the Tutorial, but don’t want to bother setting up your own schema & application, you will find the demo ingester tools useful.

如果你想测试HBase Indexer在高吞吐面而不是像教程所描述的那样手工输入,也不想设置一个自己的脚本和应用,你可以用demo提取工具。

For more information on them, please see demo/README.md in the binary distribution.

更为详细的信息,可以查看发布包中的demo/README.md

The most basic indexer configuration only requires a table name and a single field. However, there are many configuration settings that can be used in an indexer configuration file to customize behavior.

最基础索引器配置只需要一个表名和一个字段名就可以。但是,有很多配置可以用于配置可以自定义解析器的行为。

1
2
3
<indexer table="mytable">
<field name="fieldname" value="columnfamily:qualifier" type="string"/>
</indexer>

全局索引器属性(Global indexer attributes)

The following is a list of attributes that can be set on the top-level element in an indexer configuration.

以下列出的属性可以在顶层<indexer>节点中配置。

table

The table attribute specifies the name of the HBase table to be indexed by the indexer. It is the only mandatory attribute in the indexer element.

table属性用于指定HBase需要索引器索引的表名。这个indexer节点中强制要求的属性。

mapping-type

The mapping-type attribute has two possible values: row, or column. This attribute specifies whether row-based or column-based indexing is to be performed.

mapping-type属性有两种值:row和column。这个属性用于指定是基于行还是基于列的索引方式。

Row-based indexing treats all data within a single HBase row as input for a single document in Solr. This is the kind of indexing that would be used for an HBase table that contains a separate entity in each row, e.g. a table containing users.

基于行索引方式把Hbase一行当中的所有数据当成Solr的一个文档输入。这种方式用于索引一行就表示一个独立的实体的Hbase表,比如包含用户的表。

Column-based indexing treats each HBase cell as input for a single document in Solr. This approach could be used for example in a messaging platform where a single user’s messages are all stored in a single row, with each message being stored in a separate cell.

基于列索引方式把Hbase的一个列当作Solr的一个文档输入。这种处理可以用于消息平台,一个用户的所有消息存在同一行中,而每条消息存在一个单独的列上。

The default mapping-type value is row.

默认的mapping-type是row。

read-row

The read-row attribute has two possible values: dynamic, or never.

read-row属性有两种值:dyamic和never。

This attribute is only important when using row-based indexing. It specifies whether or not the indexer should re-read data from HBase in order to perform indexing.

这个属性中对基于行索引的方式才是重要的。它指定索引器为了进行索引是否需要从Hbase重新读取数据。

When set to “dynamic”, the indexer will read the necessary data from a row if a partial update to the row is performed in HBase. In dynamic mode, the row will not be re-read if all data needed to perform indexing is included in the row update.

当被设置为“dynamic”时,如果HBase是一行数据的部分数据更新时,索引器会读取这一行中需要的数据。dynamic模式下,如果是一行的全部数据的更新,索引器不会重新读取Hbase的数据。

If this attribute is set to never, a row will never be re-read by the indexer.

如果这个属性被设置为never,索引器不会重读行数据。

The default setting is “dynamic”.

默认的设置是“dynamic”。

mapper

The mapper attribute allows the user to specify a custom mapper class that will create a Solr document from a HBase Result object. The mapper class must implement the com.ngdata.hbaseindexer.parse.ResultToSolrMapper interface.

mapper属性允许用户指定一个自定义的类通过Hbase结果对象来创建Solr文档。但这个mapper类必需实现com.ngdata.hbaseindexer.parse.ResultToSolrMapper接口。

By default, the built-in com.ngdata.hbaseindexer.parse.DefaultResultToSolrMapper is used.

默认情况,使用的是内署的com.ngdata.hbaseindexer.parse.DefaultResultToSolrMapper

unique-key-formatter

The unique-key-formatter attribute specifies the name of the class used to format HBase row keys (as well as column families and column qualifiers) as text. A textual representation of these pieces of information is needed for indexing in Solr, as all data in Solr is textual, but row keys, column families, and column qualifiers are byte arrays.

unique-key-formatter指定了用于格式化Hbase rowkeys(列簇和列限定符也一样)为文本的类名。在Solr中索引需要这些信息的文本表示,因为Solr中的所有数据都是文本数据,但是行键、列族和列限定符是字节数组。

A unique-key-formatter class must implement the com.ngdata.hbaseindexer.uniquekey.UniqueKeyFormatter interface.

一个unique-key-formatter类必须实现com.ngdata.hbaseindexer.uniquekey.UniqueKeyFormatter接口。

The default value of this attribute is com.ngdata.hbaseindexer.uniquekey.StringUniqueKeyFormatter. The StringUniqueKey formatter simply treats row keys and other byte arrays as strings.

这个属性的默认值是com.ngdata.hbaseindexer.uniquekey.StringUniqueKeyFormatter。StringUniqueKeyFormatter只是简单的把rowkey或者其他字节数据当成字符串。

If your row keys, column families, or qualifiers can’t simply be used as strings, consider using the com.ngdata.hbaseindexer.uniquekey.HexUniqueKeyFormatter.

如果你的rowkey,列簇,或者限定符不能简单的用字符串表示,就你需要考虑使用com.ngdata.hbaseindexer.uniquekey.HexUniqueKeyFormatter

unique-key-field

This attribute specifies the name of the document identifier field used in Solr.

这个属性指定Solr中文档的标识字段。

The default value for this field is “id”.

默认值是“id”。

row-field

The row-field attribute specifies the name of the Solr field to be used for storing an HBase row key.

row-field属性指定了Solr中用于存储Hbase rowkey的安段名。

This field is only important when doing column-based indexing. In order for the indexer to be able to delete all documents for a single row from the index, it needs to be able to find all documents for the row in Solr. When this attribute is populated in the indexer definition, it’s value is used as the name of a field in Solr to store the encoded row key.

这个字段对于基于列索引方式才很重要。索引器为了能够从索引中删除一行的所有文档,它一个字段能在Solr中找到该行的所有文档。在索引器定义中设置这个属性时,它的值将用作Solr中字段的名称,以存储编码的行键。

By default, this attribute is empty, meaning that the row key is not stored in Solr. The consequence of this is that deleting a complete row or complete column family in HBase will not delete the indexed documents in Solr.

默认情况,这个属性为空,这意味着rowkey不会被存储在Solr里面。这样的结果就是在Hbase中删除一个完整的行或者列并不删除Solr中的已经索引的文档。

column-family-field

The column-family-field specifies the name of the Solr field to be used for storing the HBase column family name.

column-family-field指定Solr中用于存储HBase列簇名的字段名。

See the description of the row-field attribute for more information.

查看row-field属性查看更多的信息。

By default, this attribute is empty, so the column-family name is not saved in Solr.

默认情况,这个属性为空,也就是说,列簇不会被Solr存储。

table-name-field

The table-name-field specifies the name of the Solr field to be used for storing the name of the HBase table where a record is stored.

table-name-field指定Solr中用于存储Hbase表名的字段名。

By default, this attribute is empty, so the name of the HBase table is not stored unless this setting is explicitly set in the indexer config.

默认情况,这个属性是空,也就是说Hbase的表名不会被存储除非在indexer节点中明确指定。

indxer内定义的节点(Elements within the indexer definition)

There are three types of elements that can be used within an indexer configuration: , , and .

在indexer节点有三种类型的节点:,

The field element defines a single field to be indexed in Solr, as well as where its contents are to be taken from and interpreted from HBase. There are typically one or more fields listed in an indexer configuration – one for each Solr field to be stored.

field节点定义了要在Solr中索引的单个字段,以及要从Hbase获取和解析的内容。索引器配置中通常列出一个或多个字段——每个Solr字段都要存储一个字段。

The field attribute has four attributes, listed below.

field有如下的四个属性。

name

The name attribute specifies the name of a Solr field in which to store data. A field with a matching name should be defined in the Solr schema.

name属性指定了Solr的中存储数据的字段名。这个字段需要在Solr的Schema中有匹配的字段名。

The name attribute is mandatory.

name属性是必须的。

value

The value attribute specifies the data to be used from HBase for populating the field in Solr. It takes the form of a column family name and qualifier, separated by a colon.

value属性指定了Hase用于填充Solr字段的数据。它采用列族名和限定符的形式,用冒号分隔。

The qualifier portion can end in an asterisk, which is interpreted as a wildcard. In this case, all matching column-family and qualifier expressions will be used.

限定符部分可以星号结尾,该星号被解释为通配符。在这种情况下,将使用所有匹配的列族表达式和限定符表达式。

The following are examples of valid value attributes:

以下是有效值属性的示例:

  • mycolumnfamily:myqualifier
  • mycolumnfamily:my*
  • mycolumnfamily:*

source

The source attribute determines what portion of an HBase KeyValue will be used as indexing content.

Source属性确定HBASE KeyValue的哪个部分将用作索引内容。

It has two possible values: value and qualifier.、

它有两个可能的值:value和qualifier。

When value is specified (which is the case by default), then the cell value is used as input for indexing.

当指定值时(默认情况下是这种情况),则使用单元格值作为索引的输入。

When qualifier is specified, then the column qualifier is used as input for indexing.

当指定限定符时,列限定符将用作索引的输入。

type

The type attribute defines the datatype of the content in HBase.

type属性定义HBASE中内容的数据类型。

Because all data is stored in HBase as byte arrays, but all content in Solr is indexed as text, a method for converting from byte arrays to the actual datatype is needed.

因为所有数据都以字节数组的形式存储在HBASE中,但是Solr中的所有内容都被索引为文本,所以需要一个方法将字节数组转换为实际的数据类型。

The value of this field can be one of any of the datatypes supported by the HBase Bytes class: int, long, string, boolean, float, double, short, or bigdecimal.

该字段的值可以是HBASE Bytes类支持的任何数据类型之一:int、long、string、boole、Float、Double、Short或Big十进制。

If the Bytes-based representation has not been used for storing data in HBase, the name of a custom class can be specified for this attribute. The custom class must implement the com.ngdata.hbaseindexer.parse.ByteArrayValueMapper interface.

如果没有使用基于Bytes的表示形式在HBASE中存储数据,则可以为该属性指定自定义类的名称。自定义类必须实现com.ngdata.hbaseindexer.parse.ByteArrayValueMapper接口。

The element defines a key-value pair that will be supplied to custom classes that implement the com.ngdata.hbaseindexer.Configurable interface.

节点定义了一个键值对,它将提供给实现com.ngdata.hbase indexer.Configable接口的自定义类。 elements can also be nested in a element. 元素也可以嵌套在元素中。

The element has two attributes: name and value. Both are mandatory.

访节点有两个属性:name和value。两者都是必须的。

配置样例(Example configuration)

The example configuration below demonstrates all elements and attributes that can be used to configure an indexer.

下面的示例配置演示了可用于配置索引器的所有元素和属性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<!--
Do row-based indexing on table "table1", never re-reading updated content.
Store the unique document id in Solr field called "custom-id".
Additionally store the row key in a Solr field called "custom-row", and store the
column family in a Solr field called "custom-family".

Perform conversion of byte array keys using the class "com.mycompany.MyKeyFormatter".
-->
<indexer
table="table1"
mapping-type="row"
read-row="never"
unique-key-field="custom-id"
row-field="custom-row"
column-family-field="custom-family"
table-name-field="custom-table"
unique-key-formatter="com.mycompany.MyKeyFormatter"
>

<!-- A float-based field taken from any qualifier in the column family "colfam" -->
<field name="field1" value="colfam:*" source="qualifier" type="float"/>

<param name="globalKeyA" value="globalValueA"/>
<param name="globalKeyB" value="globalValueB"/>

</indexer>

参考

morphlines
morphlines-architecture

This page explains how to start doing basic indexing in HBase. Before following this tutorial, make sure that the HBase Indexer and other required software is installed and running as explained in the installation instructions.

这篇解释如何在Hbase中开始基础索引。在开始教程之前,请确保Hbase Indexer和其他需要的软件已经安装和运行。

At this point, HBase and Solr (in cloud mode) should be running, and the HBase Indexer should be unpacked in a directory (which we’ll call $INDEXER_HOME). For this tutorial, it is assumed that the default example index schema is being used by Solr (as explained on the installation page).

此时,Hbasa和Solr(云模式)已经行行,并且Hbase Indexer已经解压到一个目录中(这是我们称为$INDEXER_HOME)。在这个教程中,我们假设用的是Solr的默认example索引(就像安装中说的那样)。

启动Hbase Indexer(Start the HBase Indexer daemon)

In a terminal, execute the following (assuming $INDEXER_HOME points to the directory where the hbase-indexer tar.gz distribution was unpacked).

在终端中,运行如下命令(假定$INDEXER_HOME指向hbase-indexer tar.gz解压的目录)。

1
2
cd $INDEXER_HOME
./bin/hbase-indexer server

创建需要索引的表(Create a table to be indexed in HBase)

In the HBase shell, create a table. For this tutorial, we’ll create a table named “indexdemo-user”, with a single column family named “info”. Note that the REPLICATION_SCOPE of the column family of the table must be set to 1.

在Hbase shell,创建一个表。在这里,我们创建一个“indexdemo-user”的表,有一个“info”的列簇。注意列簇的REPLICATION_SCOPE必须设置成1。

1
2
$ hbase shell
hbase> create 'indexdemo-user', { NAME => 'info', REPLICATION_SCOPE => '1' }

添加索引器(Add an indexer)

Now we’ll create an indexer that will index the the indexdemo-user table as its contents are updated.

现在我们创建一个索引器,在indexdemo-user表的内容被更新是他会进行索引。

In your favourite text editor, create a new xml file called indexdemo-indexer.xml, with the following content:

用你喜欢的编辑器,创建一个新的xml文件,命名为indexdemo-indexer.xml,添加如下内容:

1
2
3
4
5
6
<?xml version="1.0"?>
<indexer table="indexdemo-user">
<field name="firstname_s" value="info:firstname"/>
<field name="lastname_s" value="info:lastname"/>
<field name="age_i" value="info:age" type="int"/>
</indexer>

The above file defines three pieces of information that will be used for indexing, how to interpret them, and how they will be stored in Solr.

上面的文件定义了三个索引字段的信息,如何解析,如何在Solr中存储。

Next, create an indexer based on the created indexer xml file.

接下来,基于xml文件创建一个索引器。

1
2
./bin/hbase-indexer add-indexer -n myindexer -c indexdemo-indexer.xml \
-cp solr.zk=localhost:2181/solr -cp solr.collection=collection1

Note that the above command assumes that ZooKeeper is running on localhost on port 2181, and that there is a Solr Core called “collection1” configured. If you are doing this tutorial on an existing HBase/Solr environment, you may need to use different settings.

注意上面的命令假设,ZooKeeper运行要本机的2181端口上,并且Solr Core已经创建了一个名为“collection1”的索引。如果你在一个现有的Hbase/Solr环境运行本教程,你需要修改配置。

更新表内容(Update the table content)

In the HBase shell, try adding some data to the indexdemo-user table
在Hbase shell中,尝试给indexdemo-user添加一些数据。

1
2
hbase> put 'indexdemo-user', 'row1', 'info:firstname', 'John'
hbase> put 'indexdemo-user', 'row1', 'info:lastname', 'Smith'

After adding this data, take a look in Solr (i.e. http://localhost:8983/solr/#/collection1/query). You should see a single document in Solr that has the firstname_s field set to “John”, and the lastname_s field set to “Smith”.

添加数据之后,来看一下Solr(i.e. http://localhost:8983/solr/#/collection1/quer),你应该能看到一个文档,这个文档的firstname_s字段值为“John”,同时lastname_s字段值为“Smith”。

Note If you don’t have autoCommit enabled in Solr, you won’t be able to see the updated contents immediately in Solr. The demo environment has autoCommit enabled for a commit every second.

注意如果没有开启autoCommit,你不会马上在Solr看到更新的内容。这例子的环境autoCommit已经开启并设置为每秒自动提交1次。

Now try updating the data you’ve just added

现在尝试更新你刚才添加的数据

1
hbase> put 'indexdemo-user', 'row1', 'info:firstname', 'Jim'

And now check the content in Solr. The document’s firstname_s field now contains the string “Jim”.

然后在Solr有检查内容。看下文档的firstname_s是不是变成了“Jim”

Finally, delete the row from HBase.

最后,删除Hbase的这条记录。

1
hbase> deleteall 'indexdemo-user', 'row1'

You can now verify that the data has been deleted from Solr.

你可以验证下Solr中的数据是不是已经删除了。

This page explains how to do a basic installation of the HBase Indexer on a single machine.

这篇会讲解如何在单机中进行Hbase Indexer的基础安装。

Before you start, make sure that you have the required software installed (they can all be running on single machine).

在开始之前,请确认你已经安装了所有需要的软件(他们可以都可以在单机运行)。

获取Hbase Indexer(Get the HBase Indexer)

Check out the code and build the tar.gz distribution.

签出代码并生成tar.gz的发布包。

1
2
git clone git://github.com/NGDATA/hbase-indexer.git
mvn clean package -Pdist -DskipTests

Next, unpackage the tar.gz distribution (in the example below it is unpacked under your $HOME directory).

接下来,解压tar.gz发布包(这个例子中,他被解压到$HOME目录)。

1
2
tar zxvf hbase-indexer-dist/target/hbase-indexer-1.0-SNAPSHOT.tar.gz -C ~
cd ~/hbase-indexer-1.0-SNAPSHOT

配置Hbase Indexer(Configure HBase Indexer)

In the hbase-indexer directory, edit the file conf/hbase-indexer-site.xml and configure the ZooKeeper connection string (twice, once for hbase-indexer, and once for hbase, alternatively you can copy your hbase-site.xmlto the conf directory).

hbase-indexer目录,编辑conf/hbase-indexer-site.xml 文件并配置ZooKeeper的连接串(两次,一次用于hbase-indexer,一次用于Hbase,或者你可以拷贝你的hbase-site.xml到你的conf目录)。

1
2
3
4
5
6
7
8
<property>
<name>hbaseindexer.zookeeper.connectstring</name>
<value>zookeeperhost</value>
</property>
<property>
<name>hbase.zookeeper.quorum</name>
<value>zookeeperhost</value>
</property>

If you have not defined JAVA_HOME globally, and the bin/hbase-indexer script would complain it doesn’t find you Java, you can set the JAVA_HOME in the script conf/hbase-indexer-env.sh.

如果你没有定义全局的JAVA_HOMEbin/hbase-indexer脚本会报没有找到Java,你可以通过运行conf/hbase-indexer-env.sh来设置JAVA_HOME

配置Hbase(Configure HBase)

In order to use the HBase Indexer, replication must be enabled in HBase. There are also a number of other HBase settings that can be set to optimize the working of the HBase indexer.

为了运行Hbase Indexer,复制集必须开启。同时还有一些HBase的设置需要配置以便优代Hbase Indexer的运行。

Add the settings below to your hbase-site.xml configuration on all HBase region servers, and restart HBase.
所有的分区服务上的hbase-site.xml添加如下配置,然后重启Hbase。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<configuration>
<!-- SEP is basically replication, so enable it -->
<property>
<name>hbase.replication</name>
<value>true</value>
</property>
<!-- Source ratio of 100% makes sure that each SEP consumer is actually
used (otherwise, some can sit idle, especially with small clusters) -->
<property>
<name>replication.source.ratio</name>
<value>1.0</value>
</property>
<!-- Maximum number of hlog entries to replicate in one go. If this is
large, and a consumer takes a while to process the events, the
HBase rpc call will time out. -->
<property>
<name>replication.source.nb.capacity</name>
<value>1000</value>
</property>
<!-- A custom replication source that fixes a few things and adds
some functionality (doesn't interfere with normal replication
usage). -->
<property>
<name>replication.replicationsource.implementation</name>
<value>com.ngdata.sep.impl.SepReplicationSource</value>
</property>
</configuration>

添加Indexer jar到HBase(Add indexer jars to HBase)

The HBase Indexer includes two jar files that need to be in the classpath of HBase. Copy these from the lib directory of the unpacked hbase-indexer installation into the lib directory of HBase for each region server.

Hbase Indexer包含两个jar文件需要在Hbase的类目录下。将解压目录hbase-indexer下的lib中的这些文件拷贝到所有Hbase分区服务器的lib目录。

1
cp lib/hbase-sep-* $HBASE_HOME/lib

启动Solr(Start Solr)

Ensure that Solr is running. In general, it’s easiest to have Solr use the same ZooKeeper instance as HBase.

确保Solr已经运行。通常,很容易让Hbase和Solr共用相同的ZooKeeper。

Assuming that you’ve downloaded Solr 4.2.0 and you’re running ZooKeeper on the current machine, you can start up the base Solr in cloud mode using the example schema as follows:

假设你已经下载了Solr 4.2.0并且ZooKeeper运行在当前机器,你可能通过下列脚本在云模式运行Solr。

1
2
cd $SOLR_HOME/example
java -Dbootstrap_confdir=./solr/collection1/conf -Dcollection.configName=myconf -DzkHost=localhost:2181/solr -jar start.jar

构建(Building the binary distribution)

Use the following command to build the binary distribution (.tar.gz & rpm):

使用如下命令构建生成二进制发布包(.tar.gz & rpm):

1
mvn -DskipTests -Pdist install

测试(Testing)

These steps assume a running HBase 0.94.x installation (preferably CDH 4.2), as well as a running Solr installation. For this example, the configured Solr schema will need to have a multi-valued field called “data”, as well as a unique key field called “id”.

以下这此步骤假定已经安装了Hbase 0.94.x(最好是CDH 4.2)和Solr。在这个例子中,Solr的映射,需要配置多值字段“data”和唯一键字段“id”。

  1. Enable replication and other settings that are outlined in the hbase-sep demo instructions

  2. hbase-sep demo instructions的配置复制集和其他设置。

  3. Unzip the binary distribution (instructions for creating the binary distribution are listed above).

  4. 解压发布包(生成发布包的方式已经在上文列出)。

    1
    $ tar zxvf hbase_indexer.tar.gz
  5. Copy the hbase-sep jar files from the lib directory of the binary distribution into the lib directory of HBase.

  6. 将发布包下的lib目录的hbase-sep jar文件拷贝到Hbase的lib目录。

    1
    2
    $ cd hbase_indexer
    $ sudo cp lib/hbase-sep-* /usr/lib/hbase/lib
  7. Create a table in HBase that has replication enabled. For this example, we’ll create a table called “record” with a single column family called ‘data’.

  8. 创建一个开启复制集功能的表。这个例子中,我们会创建“record”表,有一个列簇“data”。

    1
    hbase> create 'record', {NAME => 'data', REPLICATION_SCOPE => 1}
  9. Start the hbase-indexer server

  10. 启动hbase-indexer服务

    1
    $ ./bin/hbase-indexer server
  11. Create an indexer definition. For this example, we’ll just index anything in the data column family into the “data” field in Solr. Save the below contents in a file called ‘sample.xml’.

  12. 创建索引器定义。在这个例子中,我们只是把data列簇中所有内容都放到Solr的“data”字段中进行索引。将以下内容保存为”sample.xml”。

    1
    2
    3
    4
    <?xml version="1.0"?>
    <indexer table="record">
    <field name="data" value="data:*" type="string"/>
    </indexer>
  13. Add the indexer definition to the indexer server. The following command assumes that the Solr ZooKeeper is running on the current host, and the name of the collection to be used for indexing is “core0”.

  14. 把索引定义添加到inderxer服务中。下面的命令假设Solr ZooKeeper运行在当前的主机中,并且用于索引的集合名为“core0”。

    1
    $ ./bin/hbase-indexer add-indexer  -n sampleindex -c sample.xml --cp solr.collection=core0 
  15. Add some data to the record table in HBase. The data added to the data column family in the record table should show up in the Solr index.

  16. 向Hbase的recode表添加一些数据。添加到record表中的数据应该会出现在Solr的索引中。

    1
    hbase> put 'record', 'row1', 'data:value', 'Test of HBase Indexer'

The following software is required for running the HBase Indexer:

运行Hbase Indexer需要下面的这些软件:

  • HBase 0.94.x
  • Solr 4.x in cloud mode
  • ZooKeeper 3.x (required by the two above packages)

All components can be run on a single machine, or they can be run on multiple machines on a cluster.

所有的组件可以运行在单机,也可运行在多台机器的集群上。

详情(Details)

HBase

HBase 0.94.x is the supported version of HBase for the HBase Indexer. It is recommended to use the version of HBase 0.94.2 that is bundled with Cloudera CDH 4.2. However, other versions of HBase 0.94.x may also work. CDH 4.2 is currently used for testing.

Hbase 0.94.x是Hbase Indexer支持的版本。推荐使用Cloudera CDH 4.2附带的HBase 0.94.2版本。尽管,其他的0.94.x版本也能正常工作,但CDH 4.2被用于当前的测试。

HBase should be configured to use HDFS as its filesystem – HBase Indexer is not fully functional if the local filesystem implementation is used instead of HDFS.

Hbase要配置HDFS做为它的文件系统,如果使用本地文件系统而不是HDFS,HBase Indexer就不行完全运行了。

Solr

Solr 4.x is required for the HBase Indexer, and it must be configured to run in cloud mode. Solr 4.2.0 is currently used for development testing.

Hbase Indexer 需要Solr 4.x版本,并且要求配置在云模式下运行。Solr 4.2.0是当并开发测试的版本。

ZooKeeper

It is recommended that the version of ZooKeeper that is bundled in CDH 4.2 is used.

推荐使用和CDH4.2附带的ZooKeeper版本。

简介(Introduction)

The HBase Indexer project provides indexing (via Solr) for content stored in HBase. It provides a flexible and extensible way of defining indexing rules, and is designed to scale.

Hbase Indexer项目可以为存储在HBase中的内容提供Solr索引。它提供灵活的可扩展的方式来定义索引规则,且为大规模而生。

Indexing is performed asynchronously, so it does not impact write throughput on HBase. SolrCloud is used for storing the actual index in order to ensure scalability of the indexing.

索引是异步的,所以不会影响Hbase的写入吞吐量。SolrCloud用于存储实际的索引,以确保索引的可伸缩性。

开始使用Hbase Indexer(Getting started with the HBase Indexer)

  1. Make sure you’ve got the required software installed, as detailed on the Requirements page.

  2. Follow the Tutorial to get a feel for how to use the HBase Indexer.

  3. Customize your indexing setup as needed using the other reference documentation provided here.

  4. 确认所有要求的软件已经安装,具体内容在[要求]页。

  5. 按照教程来体验下如何使用Hbase Indexer。

  6. 通过提供的文档来调整索引的配置。

工作原理(How it works)

The HBase Indexer works by acting as an HBase replication sink. As updates are written to HBase region servers, they are “replicated” asynchronously to the HBase Indexer processes.

Hbase Indxer扮演了Hbase复制集的角色。当数据写入Hbase的分区时,数据被异步的“复制”给Hbase Indexer处理器。

The indexer analyzes incoming HBase mutation events, and where applicable it creates Solr documents and pushes them to SolrCloud servers.

Hbase Indexer分析从Hbase发送过来的变化事件,当合适的时候创建Solr文档并发送给SolrCloud服务器。

The indexed documents in Solr contain enough information to uniquely identify the HBase row that they are based on, allowing you to use Solr to search for content that is stored in HBase.

Solr文档维护了足够多的信息用于唯一标识一条Hbase记录,这样允许你可能通过Solr来检索Hbase内容。

HBase replication is based on reading the HBase log files, which are the precise source of truth of the what is stored in HBase: there are no missing or no extra events. In various cases, the log also contains all the information needed to index, so that no expensive random-read on HBase is necessary (see the read-rowattribute in the Indexer Configuration).

HBase复制集是通过读取Hbase的日志文件,这些日志文件是HBASE中存储内容的精确来源:没有遗漏也没有额外的事件。在大多数情况下,日志含了索引需要的全部信息,因此不需要对Hbase进行昂贵的随机读取。(在[Indexer配置]中可查看read-row属性)。

HBase replication delivers (small) batches of events. HBase-indexer exploits this by avoiding double-indexing of the same row if it would have been updated twice in a short time frame, and as well will batch/buffer the updates towards Solr, which gives important performance gains. The updates are applied to Solr before confirming the processing of the events to HBase, so that no event loss is possible.

Hbase复制集(小规模)批量分发事件。Hbase indexer利用这一特性用于避免在一个很小的时间窗口期一条记录被更新两次而引起重复索引,也通过批量/缓存的方式来更新Solr,这样可以获得更好的性能。所有的更新会在Hbase处理确认之前更新到Solr中,因此不会出现丢失数据的情况。

横向扩展(Horizontal scalability)

All information about indexers is stored in ZooKeeper. New indexer hosts can always be added to a cluster, in the same way that HBase regionservers can be added to to an HBase cluster.

所有的索引信息都是保存在ZooKeeper中的。新的Indexer主机可以被添加为一个集群中,就像Hbase的分区服务器被添加到Hbase集群一样。

All indexing work for a single configured indexer is shared over all machines in the cluster. In this way, adding additional indexer nodes allows horizontal scaling.

同一索引配置的所有索引工作被分配给集群中的所有机器。这样说来,添加额外的索引节点就可以横向扩展。

自动的错误处理(Automatic failure handling)

The HBase replication system upon which the HBase Indexer is based is designed to handle hardware failures. Because the HBase Indexer is based on this system, it also benefits from the same ability to handle failures.

Hbase复制集系统为硬件错误处理做了设计。Hbase Indexer其于此系统,因此也从中获得了错误处理的能力。

In general, indexing nodes going down or Solr nodes going down will not result in any lost data in the HBase Indexer.

通常情况,索引节点或者Solr宕机不会导致Hbase Indexer中的数据丢失。