解决从Hbase插入数据Phoenix对应索引表不同步更新问题(详细)

感谢博主:解决Hbase数据更新Phoenix对应索引表不更新问题_高矮-CSDN博客

问题描述:

        首先感谢上面博主老师的指导。参考上面博主的讲解,得出:用户访问的数据接口直接走Phoenix,也就是往hbase存取数据的话,直接从phoenix走,没有什么问题(没有问题是指:Phoenix的表是映射hbase产生,Phoenix的表会建很多索引,正常通过接口直接写数据进Phoenix表,相应的索引表也是会更新的)。

        但是如果直接往hbase中的表存数据,不走phoenix,会发现对应的索引表没有更新,也就是从phoenix上查不到数据,影响正常的访问。

解决方法:

        首先,我也是强烈建议往hbase存取数据,还是直接走phoenix,这样就不会在后面采坑。

        如果非要直接往hbase中的表存数据,不走phoenix,那么解决方法就是:

        在往hbase主表插入的同时,在对应的索引表中也插入一份。

        好了,解决方案上面博主也说了,然后也举出实例了,我主要是一方面记录我遇到此问题所解决的过程,另一方面也是对上面博主的进一步细致补充。

1.请看我的hbase表和phoenix映射表,都是一个名字:

2.对应的phoenix和hbase索引表: 

3.刚才我们说了,要想在phoenix索引表上查到数据,就要在hbase主表上插完的同时,在对应的索引表上也插入一份。

4.插入主表的代码,我在这里简略写一下:

首先是获取rowkey,这里的rowkey在下面索引表插入中会用到。

//简写
Put put = new Put(Bytes.toBytes(rowKey));
dataMap.forEach((key, value) -> {
    put.addColumn(Bytes.toBytes("data"), Bytes.toBytes(key),
            Bytes.toBytes("" + value));
});
​​​​​​​Result result = baseService.insertData(key, tableNameAndDataMap.get(key));

5.剩下的就是往索引表进行插入,这里面有两个坑:

一是拼接字符串坑。我们可以看下对应的索引表的主键是什么?看下图:

索引的主键是原表的字段组合而成的,索引表会把所有索引字段+rowkey拼接起来写进Hbase ,做为索引表的RowKey。并且组合的时候还要加上\x00这样的奇怪字段。所以我们要把字段进行拼接之后,往索引表里面插入。一开始我想到的是Stringbuilder中的append()方法,使用多次append()方法进行拼接,例如下图的方式:

        但是最后我发现自己错了。这就是第二个坑。

        二是‘\’转义的坑。起初以为直接以拼接字符串的形式往里插就可以,但是发现hbase会对\做二进制转译,‘\’会被转译为\x5c,如图:

        那现在怎么做到拼接的时候,不会出现\x5c呢,也就说不被转义呢?

解决的方案就是:

        在插入数据的时候直接以byte[] 的形式往hbase表插。

例子如下所示:



import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.hadoop.hbase.util.Bytes;

import java.util.Map;

/**
 * 插入hbase索引表 主键字段拼接
 */
public class RowKeyIndex {
    public static byte[] rowKeyIndex(Map<String, String> dataMap, String rowKey) {

        byte[] addFour;

        byte[] modelIDS = Bytes.toBytes(dataMap.get("modelID"));
        byte transformChar = (byte) 0;
        byte[] transfromChars = new byte[]{transformChar};
        byte[] addOne = ArrayUtils.addAll(modelIDS, transfromChars);
        byte[] deviceIDS = Bytes.toBytes(dataMap.get("deviceID"));
        byte[] addTwo = ArrayUtils.addAll(deviceIDS, transfromChars);

        byte[] oneAddTwo = ArrayUtils.addAll(addOne, addTwo);

        byte[] deviceTimes = Bytes.toBytes(dataMap.get("deviceTime"));
        byte[] addThree = ArrayUtils.addAll(deviceTimes, transfromChars);
        if (StringUtils.isBlank(dataMap.get("processState"))) {
            addFour = ArrayUtils.addAll(null, transfromChars);
        } else {
            byte[] processStates = Bytes.toBytes(dataMap.get("processState"));
            addFour = ArrayUtils.addAll(processStates, transfromChars);
        }


        byte[] threeAddFour = ArrayUtils.addAll(addThree, addFour);

        byte[] oneToFour = ArrayUtils.addAll(oneAddTwo, threeAddFour);

        byte[] rowKeyBytes = Bytes.toBytes(rowKey);

        byte[] rowKeyIndex = ArrayUtils.addAll(oneToFour, rowKeyBytes);

        return rowKeyIndex;
    }
}

上面的代码是我对字段拼接的过程,要注意了:

每个字段都要以如下这样的形式获取,切记!:

byte[] modelIDS = Bytes.toBytes();

然后\x00就用下面的形式解决。

byte transformChar = (byte) 0; 

byte[] transfromChars = new byte[]{transformChar};

剩下的就是把各个字段拼接在一起,可以用ArrayUtils.addAll进行拼接在一起,多用几次而已,最后返回自己的索引rowkey。

6.索引表插入的代码简写:

//调用RowKeyIndex类中的方法
byte[] rowKeyIndex = RowKeyIndex.rowKeyIndex(dataMap, rowKey);
//向表中插入数据
Put putIndex = new Put(rowKeyIndex);
//存入hbase索引表
Result resultIndex = baseService.insertData(key, tableNameAndDataMapIndex.get(key));

好了兄弟们,就到这里吧!!!!!

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 15
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阳光不锈@

如果有帮助的话,打赏一下吧

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值