HBaseEveryDay_Atomic_compare_and_set

Updated Sep 29, 2011 by lurker.h...@gmail.com

基本概念

在HBase中Insert和Update操作没有了明确的区分,那么如果我插入时不小心把以前的数据覆盖了怎么办?虽然我们可以通过timestamp将原先的数据找回,但事后弥补还是很麻烦,我想经过验证再插入库怎么办呢。 HBase中有个CAS(compare-and-set)操作用来解决这个问题(数据一致性),简单的说CAS操作可以让你在put数据之前先经过某些条件的验证,只有满足条件的put才会入库。

相关API

可以用HTable的checkAndPut(byte row, byte family, byte qualifier, byte value, Put put)方法来使用这个功能。方法的最后一个参数是你需要录入的数据的put对象,而前面的参数是与服务端check的预期值,只有服务器端对应rowkey的数据与你预期的值相同时,你的put操作才能被提交的服务端。

实战

同样写了个例子程序来验证这个功能。

package com.lurker.hbase.practise; 
 
import java.io.IOException; 
 
import org.apache.hadoop.conf.Configuration; 
import org.apache.hadoop.hbase.HBaseConfiguration; 
import org.apache.hadoop.hbase.client.HTable; 
import org.apache.hadoop.hbase.client.Put; 
import org.apache.hadoop.hbase.util.Bytes; 
 
public class CheckandPutTest { 
 
        public static void main(String[] args) throws Exception { 
                Configuration conf = HBaseConfiguration.create(); 
                conf.set("hbase.zookeeper.quorum", "132.35.81.207"); 
                conf.set("zookeeper.znode.parent", "/hbase1"); 
                HTable table = new HTable(conf, "usertable"); 
 
                Put put1 = new Put(Bytes.toBytes("row1")); 
                put1.add(Bytes.toBytes("myfam"), Bytes.toBytes("col1"), 
                                Bytes.toBytes("val1")); 
 
                // check一下,如果改列有没有值,则执行put操作。 
                boolean res1 = table.checkAndPut(Bytes.toBytes("row1"), 
                                Bytes.toBytes("myfam"), Bytes.toBytes("col1"), null,put1); 
 
                // 输出结果看是否执行了put 
                System.out.println("Put applied:" + res1); 
 
                // 再次put一条同样的记录 
                boolean res2 = table.checkAndPut(Bytes.toBytes("row1"), 
                                Bytes.toBytes("myfam"), Bytes.toBytes("col1"), null,put1); 
 
                // 输出执行结果(应当返回false) 
                System.out.println("Put applied:" + res2); 
 
                Put put2 = new Put(Bytes.toBytes("row1")); 
                put2.add(Bytes.toBytes("myfam"), Bytes.toBytes("col2"), 
                                Bytes.toBytes("val2")); 
 
                // check一下,如果之前val1录入成功,则录入新值 
                boolean res3 = table.checkAndPut(Bytes.toBytes("row1"), 
                                Bytes.toBytes("myfam"), Bytes.toBytes("col1"), 
                                Bytes.toBytes("val1"), put2); 
 
                // 输出执行结果,看是否执行了Put 
                System.out.println("Put applied:" + res3); 
 
                Put put3 = new Put(Bytes.toBytes("row2")); 
                put3.add(Bytes.toBytes("myfam"), Bytes.toBytes("col1"), 
                                Bytes.toBytes("val3")); 
 
                // check一下,row1的值是否存在,如果存在则插入row2 
                // 会抛出异常(org.apache.hadoop.hbase.DoNotRetryIOException: Action's getRow must match the passed row) 
                boolean res4 = table.checkAndPut(Bytes.toBytes("row1"), 
                                Bytes.toBytes("myfam"), Bytes.toBytes("col1"), 
                                Bytes.toBytes("val1"), put3); 
                 
                // 输出执行结果,看是否执行了Put 
                System.out.println("Put applied: " + res4); 
        } 
 
}

执行结果如下:

Put applied:true 
Put applied:false 
Put applied:true 
Exception in thread "main" org.apache.hadoop.hbase.DoNotRetryIOException:org.apache.hadoop.hbase.DoNotRetryIOException: Action's getRow must match the passed row 
        at org.apache.hadoop.hbase.regionserver.HRegion.checkAndMutate(HRegion.java:1544) 
        at org.apache.hadoop.hbase.regionserver.HRegionServer.checkAndMutate(HRegionServer.java:1740) 
        at org.apache.hadoop.hbase.regionserver.HRegionServer.checkAndPut(HRegionServer.java:1762) 
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
        at java.lang.reflect.Method.invoke(Method.java:597) 
        at org.apache.hadoop.hbase.ipc.HBaseRPC$Server.call(HBaseRPC.java:570) 
        at org.apache.hadoop.hbase.ipc.HBaseServer$Handler.run(HBaseServer.java:1039) 
 
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) 
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39) 
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27) 
        at java.lang.reflect.Constructor.newInstance(Constructor.java:513) 
        at org.apache.hadoop.hbase.RemoteExceptionHandler.decodeRemoteException(RemoteExceptionHandler.java:96) 
        at org.apache.hadoop.hbase.client.HConnectionManager$HConnectionImplementation.translateException(HConnectionManager.java:1275) 
        at org.apache.hadoop.hbase.client.HConnectionManager$HConnectionImplementation.getRegionServerWithRetries(HConnectionManager.java:1021) 
        at org.apache.hadoop.hbase.client.HTable.checkAndPut(HTable.java:754) 
        at com.lurker.hbase.practise.CheckandPutTest.main(CheckandPutTest.java:54)
  • 可以看到我们第一次check库里的row1:myfam:col1是否有值,结果是没有,成功插入数据row1:myfam:col1:val1。
  • 第二次做了与第一次同样的操作,因为刚才已经插入。row1:myfam:col1:val1,所以这次check不通过,没能插入数据。
  • 第三次new了另一个put对象,插入数据row1:myfam:col2:val2,插入之前check row1:myfam:col1:val1,同样可以成功插入数据。
  • 第四次new了一个put对象,插入数据row2:myfam:col1:val3,先check row1:myfam:col1:val1,但这时抛出异常org.apache.hadoop.hbase.DoNotRetryIOException: Action's getRow must match the passed row,可以看出checkAndPut和其他dml操作一样,都属于行级原子操作,只对单行有效。

hbase checkandput的更多相关文章

  1. hbase开发实例

    1.put/checkAndPut package com.testdata; import java.io.IOException; import org.apache.hadoop.conf.Co ...

  2. HBase中MVCC的实现机制及应用情况

    MVCC(Multi-Version Concurrent Control),即多版本并发控制协议,广泛使用于数据库系统.本文将介绍HBase中对于MVCC的实现及应用情况. MVCC基本原理 在介绍 ...

  3. Hbase之原子性插入

    /** * Created by similarface on 16/8/16. */ import java.io.IOException; import org.apache.hadoop.con ...

  4. HBase学习笔记

    关键类: HBaseAdmin 管理Hbase的,主要负责DDL操作 HTable 管理表中数据,主要负责DML操作 1.为了避免热点,更多的建表方法 在Shell中: },{SPLITS=>[ ...

  5. HBase的JavaAPI操作

    如果是DDL的操作就找HbaseAdmin. 如果是表上的增删改查的操作就找HTable. 附录代码: mport java.util.Arrays; import org.apache.hadoop ...

  6. [翻译]HBase 的 MVCC 和内建的原子操作

    翻译一篇:HBase MVCC and built-in Atomic Operations 作者:Lars Hofhansl HBase 有一些特殊的原子操作: checkAndPut, check ...

  7. HBase 二级索引与Join

    二级索引与索引Join是Online业务系统要求存储引擎提供的基本特性.RDBMS支持得比较好,NOSQL阵营也在摸索着符合自身特点的最佳解决方案. 这篇文章会以HBase做为对象来探讨如何基于Hba ...

  8. HBase篇--HBase操作Api和Java操作Hbase相关Api

    一.前述. Hbase shell启动命令窗口,然后再Hbase shell中对应的api命令如下. 二.说明 Hbase shell中删除键是空格+Ctrl键. 三.代码 1.封装所有的API pa ...

  9. HBASE 基础命令总结

    HBASE基础命令总结 一,概述 本文中介绍了hbase的基础命令,作者既有记录总结hbase基础命令的目的还有本着分享的精神,和广大读者一起进步.本文的hbase版本是:HBase 1.2.0-cd ...

随机推荐

  1. 用indexOf获取字符窜某个字符的所有位置

    indexOf方法可以传两个参数,第二个参数是传位置的参数,利用这点获取所有的位置.例如: var str = "hello world,welcome!"; var arr = ...

  2. Android替换APP字体 — Typeface

    Android替换APP字体 — Typeface APP字体的思路一般都会想到自定义控件(TextView.EditView),但是项目中会有很多种控件,就算用也会承担一些风险和资源的消耗,主要是这 ...

  3. 关于.NET异常处理的思考(上)

      年关将至,对于大部分程序员来说,马上就可以闲下来一段时间了,然而在这个闲暇的时间里,唯有争论哪门语言更好可以消磨时光,估计最近会有很多关于java与.net的博文出现,我表示要作为一个吃瓜群众,静 ...

  4. 史上最“脑残”的“抢火车票”程序(node.js版)

    [背景] 快过年了,我妈一个电话打过来叫我给他买火车票,我到12306一查,硬座和硬卧基本没有了,高铁又太贵. 最后只抢了3张无座票,但是我妈说能不能买有座位的啊,我说没有了啊,我妈:你过两天再帮我看 ...

  5. C#基础知识——类的继承

    继承是C#的三大特性之一,它实现了多态性和代码复用 我们可能会在一些类中,写一些重复的成员,我们可以将这些重复的成员,单独的封装到一个类中,作为这些类的父类. Student.Teacher.Driv ...

  6. bzoj3504: [Cqoi2014]危桥 网络流

    一种网络流建图的思路吧,改天最好整理一波网络流建图思路 #include <bits/stdc++.h> using namespace std; int n,h,t,a1,a2,an,b ...

  7. trove显示更多flavor信息

    https://review.openstack.org/#/c/352786/12 这是我目前提交的commit,如果想添加新的flavor信息可以参考这个,有几个需要注意的点是在跑py27的时候, ...

  8. [SQL基础教程] 4-1 数据的插入(INSERT)

    [SQL基础教程] C4 数据更新 4-1 数据的插入(INSERT) INSERT INSERT INTO <表名>(列1,列2...) VALUES(值1,值2...); 清单 用() ...

  9. android 控件ui

    公共参数: android:id="@+id/text_view"  给当前控件定义了 一个唯一标识符如:text_view android:layout_width=" ...

  10. iOS根据网络图片的size大小设置UIImageView的大小

    有时候在设置UIImageView的大小时候需要根据UIimage的长宽比来自动设置,不让图片原比例失真. 如果是从本地获取到的图片,[UIImage imageNamed:@"" ...