HBase协处理器是否提供跨表的任何原子性?

时间:2015-06-16 14:27:01

标签: hbase

我正在尝试使用HBase协处理器来创建二级索引。它似乎工作。我想知道这种方法是否提供任何程度的原子性。

以下是一些示例代码。它会在Put上观察tableA并在tableB中创建倒排索引:

public class MyObserver extends BaseRegionObserver {                                                                                                                                     

    public static final TableName TABLE_A = TableName.valueOf("tableA");                                                                                                            
    public static final TableName TABLE_B = TableName.valueOf("tableB");

    public static final byte[] family = Bytes.toBytes("f");                                                                                                                       
    public static final byte[] qualA = Bytes.toBytes("qualA");                                                                                                       
    public static final byte[] qualB = Bytes.toBytes("qualB");                                                                                                                 

    private Connection connection;                                                                                                                                                                                                                                                                                                                       

    @Override                                                                                                                                                                     
    public void start(CoprocessorEnvironment env) throws IOException {                                                                                                            
        Configuration config = env.getConfiguration();                                                                                                                            
        connection = ConnectionFactory.createConnection(config);                                                                                                                  
    }                                                                                                                                                                             

    @Override                                                                                                                                                                     
    public void stop(CoprocessorEnvironment env) throws IOException {                                                                                                             
        connection.close();                                                                                                                                                       
    }                                                                                                                                                                             

    @Override                                                                                                                                                                     
    public void prePut(ObserverContext<RegionCoprocessorEnvironment> env, Put put, WALEdit edit, Durability durability) throws IOException {                                      
        TableName tableName = env.getEnvironment().getRegionInfo().getTable();                                                                                                                                                                          

        if (!tableName.equals(TABLE_A)) {                                                                                                                          
            return;                                                                                                                                                               
        }                                                                                                                                                                         

        byte[] key = put.getRow();                                                                                                                                             
        byte[] value = CellUtil.cloneValue(put.get(family, qualA).get(0));                                                                                             

        Put putB = new Put(value);                                                                                                                                          
        putB.addColumn(family, qualB, key);                                                                                                                         

        try (Table tableB = connection.getTable(TABLE_B)) {                                                                                                                        
            tableB.put(putB);                                                                                                                                               
        }                                                                                                                                                                         
        catch (IOException e) {                                                                                                                                                   
            logger.info("Error: {}", e);                                                                                                                                          
        }
    }                                                        
}

我想知道:

  • 如果后续PuttableB失败,上面的PuttableA是否会被保留?
  • 相反,如果我将上面的挂钩更改为postPut()然后此挂钩的结果失败,那么触发Put的原始postPut()是否仍然成功?

2 个答案:

答案 0 :(得分:1)

使用不同的行键插入索引Put,因此这两个突变不能是原子的。显而易见的情况是将index put写入完全不同的区域服务器。

答案 1 :(得分:1)

  

如果后续的Put to tableA失败,那么上面的putB是否会被持久化?

prePut的合同是它在区域服务器上发生Put变异操作之前应用其操作。因此,如果prePut抛出异常,则调用路径被中断,请求将永远不会到达regionserver mutate操作。

  

相反,如果我将上面的钩子更改为postPut()然后这个钩子的结果失败,那么触发postPut()的原始Put是否仍然成功?

是的,相反,postPut的合同是它包含在突变向regionserver注册后应用的操作。如果从此实现中抛出异常,它将显示给调用者,但Put将在此时向HBase注册。