Apache Tephra-简介

What is Apache Tephra (TM)

 

Apache TephraApache HBase等分布式数据存储上提供全局一致的事务。虽然HBase提供了与rowregionACID操作的强大一致性,但是它牺牲了跨区域和跨表的一致性来支持可伸缩性。这种权衡要求应用程序开发人员在修改跨越区域边界时,处理确保一致性的复杂性。通过为跨地区、表或多个rpc的全球事务提供支持,Tephra简化了在HBase上的应用程序开发,而没有对许多工作负载的性能或可伸缩性产生重大影响。

ApachePhoenix也使用了Tephra,并使用完全的ACID语义添加跨行和跨表事务支持。

 

How It Works

Tephra利用HBase的本地数据版本来为事务性的读和写提供多版本的并发控制(MVCC)。使用MVCC功能,每个事务都可以看到自己的一致的数据快照,提供并发事务的快照隔离。

 

Tephra由三个主要组成部分组成:

1.      事务服务器-维护事务状态的全局视图,分配新的事务id并执行冲突检测;

2.      事务客户端-协调开始、提交和回滚事务;

3   事务处理器协处理器 -将过滤应用于读取的数据(基于给定的事务的状态),并从旧的(不再可见的)事务中清除所有数据。

 

Transaction Server

一个中央事务管理器为每个开始的事务生成一个全局惟一的基于时间的事务ID,并维护所有进行中和最近提交的冲突检测事务的状态。虽然可以并发运行多个事务服务器实例来进行自动故障切换,但一次只有一个服务器实例正在积极地提供请求。通过Apache ZooKeeper在运行的实例中执行领导选举来协调这一点。活动事务服务器实例还将使用ZooKeeper中的服务发现界面注册自身,从而允许客户端发现当前活动的服务器实例,而无需其他配置。

Transaction Client

客户端调用活动事务服务器以便启动新的事务。这将向客户端返回一个新的事务实例,其中使用唯一的事务ID(用于标识事务的写入),以及要从读取(从正在进行或无效的事务)中排除的事务ID列表。执行写入时,客户端将覆盖具有事务ID的所有修改的HBase单元的时间戳。当从HBase读取数据时,客户端将跳过与任何排除的事务ID关联的单元。读取排除通过由TransactionProcessor协处理器注入的服务器端过滤器应用。

TransactionProcessorCoprocessor

事务处理器coprocessor被加载到所有那些执行事务读和写操作的HBase表中。当客户端读取数据时,它会根据客户端事务的快照来协调执行的服务器端过滤,任何当前正在进行的事务中的数据单元,或者那些已经失败且不能回滚的(“无效事务)的数据单元将在这些读取中被跳过。此外,TransactionProcessor清理任何对任何正在运行的事务不再可见的数据版本。TransactionProcessor清理任何对任何正在运行的事务不再可见的数据版本,这要么是因为单元格关联失败的事务,要么是来自更新的事务的写入成功地提交到相同的列中。

Is It Building?

Requirements

Java Runtime

Hadoop/HBaseEnvironment

Tephra需要一个健康的HBaseHDFS环境来工作。Tephra支持组件的这些版本:

 

Disclaimer

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Tephra旨在构建一个稳定、高效、易于集群、快速扩展的JavaEE开发框架。目前,Tephra已经具备了以下特性: 提供类级别的热更新,但仅建议在需要快速修正严重BUG、并且无法立即进行全更新时使用。 提供全冗余方式的缓存,自动在每个节点间同步缓存数据,而每个节点都仅从本地内存中获取缓存数据,从而提供高效的执行效率,并且当部分节点宕机时仍旧能正常提供服务。当然,也允许使用Redis提供统一的中心节点缓存。此特性可用于多节点负载时提供不停服更新。 提供数据库读写分离、及读负载均衡,并且允许配置多个不同的数据库,甚至允许在运行期间增加新的数据库配置,并自动映射ORM。允许执行标准的SQL或存储过,同时提供了一个简单、轻量的ORM工具,并集成Hibernate、MyBatis为复杂ORM需求提供支持。 提供MongoDB工具实现对NoSQL的支持,支持负载均衡。 提供轻量级、快速响应的控制器,允许设置最大并发峰值,以确保在突如其来的并发攻击后能继续正常提供服务;也允许设置单IP最大并发量,确保小量IP并发攻击时仍能正常提供服务。允许发布为HTTP(S)、WebSocket、Socket服务。 提供JavaScript脚本引擎支持,允许JavaScript与JavaBean自由交互,并且可以发布JavaScript为服务;以及使用Javacript作为复杂规则验证器。 提供Hadoop存取支持。 模块化开发,使用注解简化配置,增强代码可读性与维护性。
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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值