HBase RowMutations для замены всех столбцов строки

У меня есть таблица HBase (v0.94.7) с одним семейством столбцов, и столбцы со временем добавляются к ней. Эти столбцы названы временной меткой, в которой они были созданы, поэтому, пока я не запрошу строку, я не знаю, какие все столбцы в ней есть.

Получив строку, я хочу атомарно удалить все существующие столбцы этого семейства столбцов и добавить новый набор столбцов и значений.

Поэтому я подумал об использовании RowMutations HBase, например:

RowMutations mutations = new RowMutations(row);

//delete the column family
Delete delete = new Delete(row);
delete.deleteFamily(cf);

//add new columns
Put put = new Put(row);
put.add(cf, col1, v1);
put.add(cf, col2, v2);

//delete column family and add new columns to same family
mutations.add(delete);
mutations.add(put);

table.mutateRow(mutations);

Но в конечном итоге этот код просто удаляет семейство столбцов, а не добавляет новые столбцы. Ожидается ли такое поведение?

Если да, то как я могу достичь своей цели атомарно заменить все столбцы семейства столбцов новым набором столбцов?

Вот тестовый пример для того же:

import junit.framework.Assert;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.HColumnDescriptor;
import org.apache.hadoop.hbase.HTableDescriptor;
import org.apache.hadoop.hbase.TableExistsException;
import org.apache.hadoop.hbase.client.*;
import org.apache.hadoop.hbase.util.Bytes;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

import java.util.NavigableMap;

public class TestHBaseRowMutations {
    static String tableName = "nnn";
    static byte[] cf1 = Bytes.toBytes("cf1");
    static byte[] row = Bytes.toBytes("r1");
    static HTablePool hTablePool;

    @BeforeClass
    public static void beforeClass() throws Exception {
        Configuration config = HBaseConfiguration.create();
        hTablePool = new HTablePool(config, Integer.MAX_VALUE);
        HBaseAdmin admin = new HBaseAdmin(config);
        HTableDescriptor tableDescriptor = new HTableDescriptor(tableName);
        tableDescriptor.addFamily(new HColumnDescriptor(cf1));
        try {
            admin.createTable(tableDescriptor);
        } catch (TableExistsException ignored){}
    }

    @Before
    public void before() throws Exception {
        HTableInterface table = hTablePool.getTable(tableName);
        try {
            Delete delete = new Delete(row);
            table.delete(delete);
            System.out.println("deleted old row");

            Put put = new Put(row);
            put.add(cf1, Bytes.toBytes("c1"), Bytes.toBytes("v1"));
            put.add(cf1, Bytes.toBytes("c11"), Bytes.toBytes("v11"));
            table.put(put);
            System.out.println("Created row with seed data");
        } finally {
            table.close();
        }
    }


    @Test
    public void testColumnFamilyDeleteRM() throws Exception {
        HTableInterface table = hTablePool.getTable(tableName);
        try {
            RowMutations rm =new RowMutations(row);

            //delete column family cf1
            Delete delete = new Delete(row);
            delete.deleteFamily(cf1);
            rm.add(delete);
            System.out.println("Added delete of cf1 column family to row mutation");

            //add new columns to same column family cf1
            Put put = new Put(row);
            put.add(cf1, Bytes.toBytes("c1"), Bytes.toBytes("new_v1"));
            put.add(cf1, Bytes.toBytes("c11"), Bytes.toBytes("new_v11"));
            rm.add(put);
            System.out.println("Added puts of cf1 column family to row mutation");

            //atomic mutate the row
            table.mutateRow(rm);
            System.out.println("Mutated row");

            //now read the column family cf1 back
            Result result = table.get(new Get(row));
            NavigableMap<byte[], byte[]> familyMap = result.getFamilyMap(cf1);

            //column family cf1 should have 2 columns because of the Put above
            //------Following assert fails as cf1 does not exist anymore, why does cf1 not exist anymore?-------
            Assert.assertNotNull(familyMap);
            Assert.assertEquals(2, familyMap.size());
        } finally {
            table.close();
        }
    }
}

person vinodv26    schedule 26.05.2013    source источник
comment
Может быть, вы удаляете семейство столбцов, а не сами столбцы?   -  person Cihan Keser    schedule 26.05.2013
comment
Как упоминалось выше, я заранее не знаю имена столбцов, поэтому да, я удаляю семейство столбцов с помощью delete.deleteFamily(cf); а затем добавить новые столбцы с помощью put.add(cf, col1, v1);...   -  person vinodv26    schedule 26.05.2013


Ответы (3)


Отправил тот же вопрос на форуме пользователей HBase и оказалось, что это ошибка в HBase.

Ожидаемое поведение заключается в том, что если RowMutation имеет Delete для некоторого семейства столбцов/столбца/строки, за которым следует Put для того же семейства столбцов/столбца/строки, то Put также должен соблюдаться (но в настоящее время это не так).

Обсуждение этого в группе пользователей HBase: http://apache-hbase.679495.n3.nabble.com/Using-RowMutations-to-replace-all-columns-of-a-row-td4045247.html

HBase JIRA для того же: https://issues.apache.org/jira/browse/HBASE-8626, который также предоставляет патч.

person vinodv26    schedule 27.05.2013

Самое близкое, что можно сделать, это установить отметку времени на Put выше, чем на Delete:

long now = System.currentTimeMillis();

Delete delete = new Delete(row);
delete.deleteFamily(cf1, now);

Put put = new Put(row);
put.add(cf1, col1, now + 1);

RowMutations mutations = new RowMutations(row);
mutations.add(delete);
mutations.add(put);

table.mutateRow(mutations);

К сожалению, это означает, что get к метке времени «сейчас» не будет иметь ничего в этом семействе столбцов. Источник

person EmDash    schedule 11.02.2016

Получил сценарий для совместного использования. Когда мы пытаемся выполнить List of RowMutations, каждый из которых может содержать действительный Put для ROW1: CF1: Q1: V1 и Delete для ROW1: CF2: Q1: V1 в качестве массовой операции hbase, и получил ошибку ниже

java.lang.RuntimeException: java.lang.UnsupportedOperationException: нет RowMutations в многократных вызовах; используйте mutateRow в org.apache.hadoop.hbase.client.RpcRetryingCaller.callWithoutRetries(RpcRetryingCaller.java:218) в org.apache.hadoop.hbase.client.AsyncProcess$AsyncRequestFutureImpl$SingleServerRequestRunnable.run(AsyncProcess.java:748) в java .util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) в java.util.concurrent.FutureTask.run(FutureTask.java:266) в java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ) в java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) в java.lang.Thread.run(Thread.java:748)

Чтобы решить эту проблему, мы решили выполнять каждую мутацию строки отдельно. Любые предложения, которые вы получили, приветствуются.

person Kamal    schedule 16.05.2019