Tephra

HBase 全局一致性事务支持
授权协议 Apache
开发语言 Java
所属分类 服务器软件、 分布式应用/网格
软件类型 开源软件
地区 不详
投 递 者 卫嘉谊
操作系统 跨平台
开源组织
适用人群 未知
 软件概览

Tephra 在 Apache HBase 的基础上提供了全局一致性的事务支持。HBase 提供了强一致性的基于行和区域的 ACID 操作支持,但是牺牲了在跨区域操作的支持。这就要求应用开发者花很大力气来确保区域边界上操作的一致性。而 Tephra 提供了全局事务支持,可以夸区域、跨表以及多个 RPC 上简化了应用的开发。

示例代码:

  /**
   * A Transactional SecondaryIndexTable.
   */
  public class SecondaryIndexTable {
    private byte[] secondaryIndex;
    private TransactionAwareHTable transactionAwareHTable;
    private TransactionAwareHTable secondaryIndexTable;
    private TransactionContext transactionContext;
    private final TableName secondaryIndexTableName;
    private static final byte[] secondaryIndexFamily =
      Bytes.toBytes("secondaryIndexFamily");
    private static final byte[] secondaryIndexQualifier = Bytes.toBytes('r');
    private static final byte[] DELIMITER  = new byte[] {0};

    public SecondaryIndexTable(TransactionServiceClient transactionServiceClient,
                               HTable hTable, byte[] secondaryIndex) {
      secondaryIndexTableName =
            TableName.valueOf(hTable.getName().getNameAsString() + ".idx");
      HTable secondaryIndexHTable = null;
      HBaseAdmin hBaseAdmin = null;
      try {
        hBaseAdmin = new HBaseAdmin(hTable.getConfiguration());
        if (!hBaseAdmin.tableExists(secondaryIndexTableName)) {
          hBaseAdmin.createTable(new HTableDescriptor(secondaryIndexTableName));
        }
        secondaryIndexHTable = new HTable(hTable.getConfiguration(),
                                          secondaryIndexTableName);
      } catch (Exception e) {
        Throwables.propagate(e);
      } finally {
        try {
          hBaseAdmin.close();
        } catch (Exception e) {
          Throwables.propagate(e);
        }
      }

      this.secondaryIndex = secondaryIndex;
      this.transactionAwareHTable = new TransactionAwareHTable(hTable);
      this.secondaryIndexTable = new TransactionAwareHTable(secondaryIndexHTable);
      this.transactionContext = new TransactionContext(transactionServiceClient,
                                                       transactionAwareHTable,
                                                       secondaryIndexTable);
    }

    public Result get(Get get) throws IOException {
      return get(Collections.singletonList(get))[0];
    }

    public Result[] get(List<Get> gets) throws IOException {
      try {
        transactionContext.start();
        Result[] result = transactionAwareHTable.get(gets);
        transactionContext.finish();
        return result;
      } catch (Exception e) {
        try {
          transactionContext.abort();
        } catch (TransactionFailureException e1) {
          throw new IOException("Could not rollback transaction", e1);
        }
      }
      return null;
    }

    public Result[] getByIndex(byte[] value) throws IOException {
      try {
        transactionContext.start();
        Scan scan = new Scan(value, Bytes.add(value, new byte[0]));
        scan.addColumn(secondaryIndexFamily, secondaryIndexQualifier);
        ResultScanner indexScanner = secondaryIndexTable.getScanner(scan);

        ArrayList<Get> gets = new ArrayList<Get>();
        for (Result result : indexScanner) {
          for (Cell cell : result.listCells()) {
            gets.add(new Get(cell.getValue()));
          }
        }
        Result[] results = transactionAwareHTable.get(gets);
        transactionContext.finish();
        return results;
      } catch (Exception e) {
        try {
          transactionContext.abort();
        } catch (TransactionFailureException e1) {
          throw new IOException("Could not rollback transaction", e1);
        }
      }
      return null;
    }

    public void put(Put put) throws IOException {
      put(Collections.singletonList(put));
    }


    public void put(List<Put> puts) throws IOException {
      try {
        transactionContext.start();
        ArrayList<Put> secondaryIndexPuts = new ArrayList<Put>();
        for (Put put : puts) {
          List<Put> indexPuts = new ArrayList<Put>();
          Set<Map.Entry<byte[], List<KeyValue>>> familyMap = put.getFamilyMap().entrySet();
          for (Map.Entry<byte [], List<KeyValue>> family : familyMap) {
            for (KeyValue value : family.getValue()) {
              if (value.getQualifier().equals(secondaryIndex)) {
                byte[] secondaryRow = Bytes.add(value.getQualifier(),
                                                DELIMITER,
                                                Bytes.add(value.getValue(),
                                                DELIMITER,
                                                value.getRow()));
                Put indexPut = new Put(secondaryRow);
                indexPut.add(secondaryIndexFamily, secondaryIndexQualifier, put.getRow());
                indexPuts.add(indexPut);
              }
            }
          }
          secondaryIndexPuts.addAll(indexPuts);
        }
        transactionAwareHTable.put(puts);
        secondaryIndexTable.put(secondaryIndexPuts);
        transactionContext.finish();
      } catch (Exception e) {
        try {
          transactionContext.abort();
        } catch (TransactionFailureException e1) {
          throw new IOException("Could not rollback transaction", e1);
        }
      }
    }
  }


  • 一年多了,Tephra总算开始展现出迷人的风采了。也许Tephra不会是我的最后一个底层架构框架,但至少在接下来的几年里,应该就是他了。 Tephra取火山灰之意,因为当初好像刚好有个火山喷发了,而且觉得火山灰是一个毁灭者,但同时又是一个创造者。他毁灭了旧的体系,然后开始用他自己的养分创造新的体系。目前看来,他确实已经毁灭了我之前的架构(封印在SVN上很久了),接下来就看看他如何创建一个新的体系了

  •   一.     下载源代码并编译打包: git clone https://git-wip-us.apache.org/repos/asf/incubator-tephra.git cd incubator-tephra mvn clean package 二.     编译完成后,在tephra-distribution/target/ directory包下拿到 tephra-<versio

  • Tephra 在 Apache HBase 的基础上提供了全局一致性的事务支持。HBase 提供了强一致性的基于行和区域的 ACID 操作支持,但是牺牲了在跨区域操作的支持。这就要求应用开发者花很大力气来确保区域边界上操作的一致性。而 Tephra 提供了全局事务支持,可以夸区域、跨表以及多个 RPC 上简化了应用的开发。 示例代码: /** * A Transactional Second

  • What is Apache Tephra (TM)   Apache Tephra在Apache HBase等分布式数据存储上提供全局一致的事务。虽然HBase提供了与row或region级ACID操作的强大一致性,但是它牺牲了跨区域和跨表的一致性来支持可伸缩性。这种权衡要求应用程序开发人员在修改跨越区域边界时,处理确保一致性的复杂性。通过为跨地区、表或多个rpc的全球事务提供支持,Tephra

  • 随着移动端的风靡,早先那种基于HTML/XML数据传输的系统架构已经无法满足开发需求了,因此重新做了底层框架,并名之曰Tephra。Tephra默认采用JSON作为数据格式,可以在各个终端中快乐地工作着。 Tephra拥有以下几个功能包: core——核心组件包; dao——持久化组件包; ctrl——控制组件包; ctrl-http——基于HTTP的控制组件包; script——JavaScri

 相关资料
  • 全局属性 全局属性通过 fis.set 设置,通过 fis.get 获取; 内置的默认配置 var DEFAULT_SETTINGS = { project: { charset: 'utf8', md5Length: 7, md5Connector: '_', files: ['**'], ignore: ['node_modules/**', 'ou

  • 我正在计划一个使用事件源的微服务模型。为了实现高可伸缩性和高吞吐量处理能力,我将使用Kafka作为微服务的消息代理。 在这一点上,我有问题的实现模型,以能够拥有Kafka主题和分区的好处。我的模型需要满足一些要求: 微服务必须从message broker获取数据(post/patch/put/delete) 数据一致性是强制性的,如果实体A需要实体B的先前存在,则必须只存在实体A的指向实体B的有

  • 有人能帮助我如何通过datastax.cassandraconnector设置一致性吗?

  • 使用CQRS和事件存储,微服务之间的编排提供了最终的一致性,其中一个微服务中的更改需要一点时间传播到其他相关的下游系统(本质上是其他微服务)。如果数据非常关键,以至于两个微服务都应该具有很强的数据一致性,那么有什么选择呢?我能想到的一个选择是像数据网格那样的直写缓存,但这非常脆弱,特别是在分布式系统中。

  • 我们继续上一章节的内容,大家应该记得我们 Lua 代码中是如何完成 ngx_postgres 模块调用的。我们把他简单改造一下,让他更接近真实代码。 local json = require "cjson" function db_exec(sql_str) local res = ngx.location.capture('/postgres',

  • EasySwoole有四个全局事件,全部位于框架安装后生成的EasySwooleEvent.php中。 frameInitialize 框架初始化事件 mainServerCreate 主服务创建事件 onRequest Http请求事件 afterAction Http响应后事件 frameInitialize mainServerCreate onRequest afterAction

  • Hibernate会支持MongoDB事务吗? MongoDB4.0增加了对多文档ACID事务的支持。但是Hibernate仍然不支持这一点,我不能简单地使用@transactional(Grails framework)注释为MongoDB操作添加事务性行为。我得自己写事务性管理代码。有没有人有更好的解决方案或者什么时候Hibernate支持它?谢谢! 引自Hibernate:MongoDB不支

  • 请求方法结束后执行 假如你使用了单例模式,需要清理请求时的GET POST 等全局变量或本次请求的日志运行记录,就可以在此方法内执行。 protected function afterAction( $actionName ) : void 示例 想一下,我如果想知道那些请求的执行时间长短,或者记录一些所谓的 慢请求, 那幺我们可以通过两个事件 onRequest 和当前这个 afterActio