• hbase checkandput


    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操作一样,都属于行级原子操作,只对单行有效。
  • 相关阅读:
    angularjs1-8,cacheFactory,sce
    angularjs1-7,http,location
    angularjs1-7,供应商
    angularjs1-6,自定义服务
    UI设计师不可不知的安卓屏幕知识-安卓100分享
    k8s ingres 的安装与使用
    get、put、post、delete含义与区别
    [影像技术与PACS] 从技术角度看国内部份PACS厂商
    UML类图符号 各种关系说明以及举例
    理解 Delphi 的类(八)
  • 原文地址:https://www.cnblogs.com/Evil-Rebe/p/6143839.html
Copyright © 2020-2023  润新知