日期:2014-05-16  浏览次数:20518 次

HBase的辅助索引实现


翻译自http://wiki.apache.org/hadoop/Hbase/SecondaryIndexing

?

本文是关于实现HBase辅助索引不同方法的设计文档。

?

使用Coprocessor实现最终一致性的辅助索引

?基本的想法是为主表中的每个索引建立一个额外的辅助表。为列族(family)添加coprocessor,并利用coprocessor处理列族上(或指定的列)的辅助索引。用WAL(write ahead log)来保证持久性,并使用共享队列保证辅助索引的更新在调用者看来是异步的。通常HBase的时间戳可以决绝所有的解决,并且可以保证操作是幂等的(多次重复操作与一次操作等价)。


?当向主表进行Put操作时,会顺序执行以下过程(假设不同的索引更新到不同的辅助表):

?


  1. 为主表生成WALEdit
  2. 为辅助表的更新生成特殊的WALEdit
  3. 将以上两个WALEdit同步到Hlog
  4. 将主表的更改应用到MemStore,并提交到RWCC(MVCC,MultiVersionConsistencyControl)
  5. 将辅助表的更改添加到共享工作队列
  6. 返回给客户端


?

共享队列是一个线程或线程池,通过应用标准的Put操作处理辅助表的更改。

?

当主表故障恢复时,主表的更改可以正常回放,辅助索引的更改需要通过共享队列应用到辅助表(服务器)上。

?

主要的问题在于如何处理WAL和回放

?

由于其他RS(RegionServer)可能会失效,辅助表可能处于离线状态,这可能导致长时间等待辅助表的更新。当收回旧的HLog日志时,如何才能保证所有辅助表已经获得更新?同时,我们需要避免过度利用幂等操作,不只是过度的重新应用所有的操作。

?

是否需要跟踪每个Hlog和它正在进行的辅助表更新操作并阻止日志回收操作,直到所有的操作完成?

?

还是当操作已经完成时,将辅助表的更改写回到WAL中?(这样辅助表失效时不需要回放)

?

或者,可以把辅助表的更改关联到每个上memstore,只有当所有的辅助表内的数据都写入完成后,memstore才可以做flush操作,这可以与现有的语义的日志回收相匹配...但这样做有其他方面的影响,并不会真正解决过多的回放的问题。

?