Предварительное знакомство с HBase: архитектура + принцип + сравнение + практика

MySQL HBase

Поскольку работа требует использования HBase, исследуется контент, связанный с HBase. Цель написания этой статьи — не только подвести итоги предыдущей работы, но и помочь студентам, которые заняты, но хотят разобраться в HBase. В процессе написания этой статьи контент, связанный с MySQL, будет перемежаться, надеясь помочь понять HBase.

В этой статье в основном обсуждаются следующие вопросы. Описанное содержание предназначено только для личного размышления, и мнения ограничены. Если есть какие-либо ошибки, пожалуйста, критикуйте и исправьте.

  • Что такое HBase? Какова его структура?
  • Как HBase управляет данными?
  • HBase — это распределенная база данных, как маршрутизируются данные?
  • Применимые сценарии для HBase?
  • Каковы основные различия между HBase и MySQL?
  • Как использовать HBase? Как реализовать операции CREATE, INSERT, SELECT, UPDATE, DELETE, LIKE?

1 HBase

1.1 Архитектура HBase

Что такое HBase? Какова его структура?

HBase (Hadoop DataBase) — нереляционная распределенная база данных (NoSQL), поддерживающая массовое хранение данных (официально: одна таблица поддерживает десятки миллиардов строк и миллионы столбцов). HBase использует классическую архитектуру master-slave, нижний уровень опирается на HDFS и использует ZooKeeper в качестве службы совместной работы.Его архитектура примерно следующая:


в,

  • Мастер: узел управления HBase. Управляйте региональными серверами, назначайте регионы региональным серверам, предоставляйте возможности балансировки нагрузки, выполняйте операции DDL, такие как создание таблиц.
  • Региональный сервер: узел данных HBase. Управление регионами.Сервер регионов может содержать несколько регионов.Регионы эквивалентны разделам таблицы. Клиент может напрямую связываться с региональным сервером для реализации операций DML, таких как добавление, удаление, изменение и запрос данных.
  • ZooKeeper: Координационный центр. Отвечает за выбор мастера, координацию узлов и хранение метаданных, таких как hbase:meta.
  • HDFS: базовая система хранения. Отвечает за хранение данных, данные в регионе хранятся через HDFS.

Имея базовое представление о HBase в целом, я думаю, что есть несколько важных моментов, на которые стоит обратить внимание: модель данных HBase, концепция Region и маршрутизация данных.

1.2 Модель данных HBase

Как HBase управляет данными? (логический слой)

Модель данных HBase сильно отличается от реляционных баз данных, таких как MySQL, которая представляет собой концепцию «гибкой схемы».

  1. В размерности таблицы она содержит несколько строк, каждая строка отличается RowKey.
  2. В измерении строк оно содержит несколько семейств столбцов.Семейства столбцов аналогичны классификации столбцов, но это не просто логические понятия.Основное физическое хранилище также различается семействами столбцов (одно семейство столбцов соответствует одному магазину в разных регионах). ).
  3. В измерении семейства столбцов, содержащем несколько столбцов, столбцы являются динамическими. Это не столбец, а пара ключ-значение, где Key — это имя столбца, а Value — значение столбца.

Структура таблицы HBase выглядит следующим образом:


  • RowKey (ключ строки): RowKey упорядочен по словарю, а HBase реализует индексирование на основе RowKey;
  • Семейство столбцов: вертикальный разрез, в строке может быть несколько семейств столбцов, а в семействе столбцов может быть любое количество столбцов;
  • Ключ-значение (пара ключ-значение): в каждом столбце хранится пара ключ-значение, ключ — это имя столбца, а значение — значение столбца;
  • Байт (тип данных): данные хранятся в байтах в HBase, а фактический тип данных преобразуется пользователем;
  • Версия (мультиверсия): каждый столбец может быть настроен с соответствующей версией для получения данных указанной версии (по умолчанию возвращается последняя версия);
  • Разреженная матрица: количество столбцов может варьироваться от строки к строке, но место для хранения занимают только фактические столбцы.

1.3 Region

Как HBase управляет данными? (физический слой)

Регион — это понятие в HBase, аналогичное разделу в СУБД.

  1. Регион — это горизонтальный срез таблицы.Таблица состоит из одного или нескольких регионов, и регионы назначаются каждому серверу регионов;
  2. Регион разделен на несколько Stores в соответствии с семейством столбцов, каждое Store состоит из MemStore и StoreFile; данные записываются в MemStore, MemStore аналогичен входному буферу, который после сохранения является StoreFile; журнал WAL обновляется одновременно по мере записи данных и использования WAL для восстановления после сбоя для обеспечения безопасности чтения и записи данных;
  3. StoreFile соответствует HFile, который хранится в HDFS.

Вот моя грубая модель:


1) Регион представляет собой диапазон RowKey.

Каждый регион на самом деле представляет собой диапазон RowKey. Например, диапазон RowKey, хранящийся в регионе A, — это [aaa,bbb], диапазон RowKey, хранящийся в регионе B, — [bbb,ccc) и т. д. Регионы также хранятся упорядоченным образом на сервере регионов, и регион A должен располагаться перед регионом B.

Примечание. RowKey разработан как aaa вместо числа, такого как 1001, чтобы подчеркнуть, что RowKey — это не только число, если допустимы символы, которые можно отсортировать лексикографически, например: abc-123456 .


2) Данные направляются в каждый регион

Таблица состоит из одного или нескольких регионов (логических), а сервер регионов содержит один или несколько регионов (физических). Маршрутизация данных должна сначала найти область, в которой хранятся данные таблицы. Расположение таблицы напрямую зависит от имени таблицы, а расположение области основано на RowKey (поскольку каждая область является диапазоном RowKey). , поэтому легко узнать соответствующий RowKey в соответствии с диапазоном RowKey. Region).

Примечание: Мастер использует стратегию DefaultLoadBalancer для назначения регионов серверам регионов по умолчанию.Подобно методу опроса, он может гарантировать, что каждый сервер регионов имеет одинаковое количество регионов (здесь количество регионов одинаково, но по-прежнему возможно, что горячие точки собираются в регионе, поэтому горячие точки собираются на региональном сервере).


3) Когда таблица слишком велика, регион автоматически разделяется.

  • автоматическое разделение

До версии 0.94 политика разделения регионов была ConstantSizeRegionSplitPolicy , которая запускала разделение на основе фиксированного значения.

После версии 0.94 политика разделения по умолчанию имеет значение IncreasingToUpperBoundRegionSplitPolicy, которое будет определяться на основе количества регионов и максимального значения StoreFile. Когда количество регионов меньше 9 и максимальное значение StoreFile меньше определенного значения, регион разделяется; когда количество регионов больше 9, используется ConstantSizeRegionSplitPolicy.

  • разделить вручную

В разделе ConstantSizeRegionSplitPolicy управляйте разделением регионов, задав hbase.hregion.max.filesize.


1.4 Маршрутизация данных hbase:meta

HBase — это распределенная база данных, как маршрутизируются данные?

Маршрутизация данных осуществляется с помощью таблицы hbase:meta, которая записывает метаданные всех регионов, а местоположение hbase:meta записывается в ZooKeeper.

Примечание. Некоторые старые статьи могут ссылаться на таблицы .root и .meta. На самом деле таблицы .root и .meta были разработаны до версии HBase 0.96. После версии 0.96 таблица .root была удалена, а таблица .meta была переименована в hbase:meta.

Формат таблицы hbase:meta следующий:


в,

  • таблица: имя таблицы;
  • начальный ключ региона: первый RowKey в регионе, если начальный ключ региона пуст, это означает, что регион является первым регионом;
  • идентификатор региона: идентификатор региона, обычно метка времени создания региона;
  • regioninfo: сериализованное значение HRegionInfo этого региона;
  • server: адрес Регионального Сервера, на котором находится Регион;
  • serverstartcode: время запуска регионального сервера, на котором находится регион.

Процесс записи данных:

Содержание данных необходимо указывать, когда данные написаны.

  1. Клиент HBase обращается к ZooKeeper, получает адрес hbase:meta и кэширует этот адрес;
  2. Получите доступ к hbase:meta соответствующего регионального сервера;
  3. Получите адрес сервера региона, соответствующий RowKey, из таблицы hbase:meta и кэшируйте адрес;
  4. Клиент HBase напрямую запрашивает региональный сервер для завершения чтения и записи данных в соответствии с адресом.

Примечание 1. Маршрутизация данных не требует участия Мастера, что означает, что операция DML не требует участия Мастера. С помощью hbase:meta клиент напрямую связывается с сервером регионов для маршрутизации, чтения и записи данных.

Примечание 2. После того, как клиент получит адрес hbase:meta, он кэширует информацию об адресе, чтобы уменьшить доступ к ZooKeeper. В то же время клиент ищет hbase:meta по RowKey, и после получения соответствующего адреса Region Server он также кэширует адрес, чтобы уменьшить доступ к hbase:meta. Поскольку таблица hbase:meta хранится на региональном сервере, ее размер может быть большим, поэтому полное содержимое hbase:meta не будет кэшироваться.


1.5 Применимые сценарии HBase

  1. Приложения, не требующие сложных запросов. HBase изначально поддерживает только индексы на основе RowKey. Для некоторых сложных запросов (таких как нечеткие запросы, запросы с несколькими полями) HBase может потребоваться полное сканирование таблицы для получения результатов.
  2. Приложения, требующие интенсивной записи. HBase — это система, которая быстро пишет и медленно читает (медленность относительная). HBase разработан на основе Google BigTable, и типичное приложение предназначено для непрерывной вставки новых данных (например, информации о веб-странице Google).
  3. Приложения с низкими требованиями к транзакциям. HBase поддерживает только транзакции на основе RowKey.
  4. Приложения, требующие высокой производительности и надежности. HBase не имеет единой точки отказа и обеспечивает высокую доступность.
  5. Приложения с особенно большим объемом данных. HBase поддерживает объем данных в десятки миллиардов строк и миллионы столбцов.Если один регион слишком велик, он автоматически запускает разделение и имеет лучшую масштабируемость.

2 В чем разница между HBase и MySQL?

Каковы основные различия между HBase и MySQL?

2.1 MySQL

Структура таблицы MySQL обычная, каждая строка имеет фиксированные столбцы.

  • При создании таблицы необходимо указать имя таблицы, количество предустановленных полей (столбцов) и тип данных.Схема фиксированная.
  • При вставке данных просто заполните значение каждого столбца в соответствии со схемой таблицы. Если в схеме нет столбца, его нельзя вставить.

2.2 HBase

HBase поддерживает динамические столбцы, разные строки могут иметь разное количество столбцов, а новые столбцы можно добавлять динамически. Структура таблиц HBase выглядит неорганизованной, но она хороша для хранения разреженных данных.

  • При создании таблицы необходимо указать имя таблицы и семейство столбцов, но не нужно указывать количество и тип данных столбцов.Схема является гибкой.
  • При вставке данных необходимо указать имя таблицы, семейство столбцов, RowKey, несколько столбцов (имя столбца и значение столбца), где количество столбцов может быть один или несколько.

2.3 Сравнение

Далее, предполагая, что в таблице ct_account_info_demo есть только одна запись (account_id = 1, account_owner = Owner1, account_amount = 23.0, is_deleted = n), найдите эту запись через MySQL и HBase соответственно.

Результат, возвращаемый MySQL:

mysql> select * from ct_account_info_demo;
+------------+---------------+----------------+------------+
| account_id | account_owner | account_amount | is_deleted |
+------------+---------------+----------------+------------+
|     1      |     Owner1    |      23.0      |     n      |
+------------+---------------+----------------+------------+
1 rows in set (0.01 sec)

Результат, возвращаемый HBase:

hbase(main):001:0> scan 'ct_account_info_demo';
ROW           COLUMN+CELL
 1            column=CT:account_amount, timestamp=1532502487735, value=23.0
 1            column=CT:account_id, timestamp=1532909576152, value=1
 1            column=CT:account_owner, timestamp=1532502487528, value=Owner1
 1            column=CT:is_deleted, timestamp=1532909576152, value=n

Вышеуказанные результаты представляют собой строку данных.Результаты, возвращаемые MySQL, интуитивно понятны и просты для понимания.

Результат, возвращаемый HBase, фактически представляет собой несколько пар ключ-значение. ROW представляет RowKey данных, а COLUMN+CELL представляет содержимое, соответствующее RowKey.

В COLUMN+CELL есть несколько пар ключ-значение, например:

column=CT:account_amount, timestamp=1532502487735, value=23.0

Столбец account_amount, представляющий семейство столбцов CT, имеет значение 23,0 и отметку времени 1532502487735 .

Примечание. ROW равно 1, потому что здесь RowKey = {account_id}, CT — это предопределенное семейство столбцов (HBase необходимо указать RowKey и семейство столбцов при вставке данных).

В основном,

  1. HBase имеет больше концепций RowKey и Column Family, чем MySQL.RowKey здесь похож на первичный ключ в MySQL, а Column Family эквивалентен «классификации» нескольких столбцов.
  2. Когда имеется только одно семейство столбцов, схема HBase и MySQL может быть согласованной, но HBase позволяет некоторым полям быть пустыми или динамически добавлять столбец, в то время как MySQL может только заполнять соответствующий столбец в соответствии со схемой и не может динамически увеличиваться или увеличиваться. уменьшить столбцы.
  3. Поскольку схема HBase не является фиксированной, каждая вставка и поиск данных не так лаконичны, как MySQL.HBase необходимо указывать такую ​​информацию, как ключи строк, семейства столбцов и столбцы.

Более подробное сравнение показано в следующей таблице (цитата из:Язык Лаймана HBase):

RDBMS HBase
аппаратная архитектура Традиционные многоядерные системы, дорогое оборудование Распределенные кластеры типа Hadoop с низкими затратами на оборудование
Отказоустойчивость Как правило, для реализации механизма высокой доступности требуются дополнительные аппаратные устройства. Благодаря программной архитектуре из-за нескольких узлов нет единой точки отказа, о которой можно было бы беспокоиться.
размер базы данных ГБ, ТБ PB
расположение данных организованы в строки и столбцы Разреженная, распределенная, многомерная карта
тип данных Богатые типы данных Bytes
Сопровождение сделки Полная поддержка ACID для строк и таблиц ACID поддерживает только один уровень строки
язык запросов SQL Поддерживает только Java API (если не используется с другими фреймворками, такими как Phoenix, Hive)
показатель служба поддержки Поддерживается только Row-key (если не используется с другими технологиями, такими как Phoenix, Hive)
пропускная способность тысяч запросов в секунду млн запросов в секунду

3 операции, связанные с HBase (CRUD)

Как использовать HBase? Как реализовать операции CREATE, INSERT, SELECT, UPDATE, DELETE, LIKE?

Для простоты понимания операции DML HBase описываются в связи с MySQL, а также способы использования HBase для реализации CREATE, INSERT, SELECT, UPDATE, DELETE и LIKE операций MySQL.

Чтобы облегчить повторное использование кода, код для получения соединений HBase инкапсулируется заранее:

// 获取HBase连接
public Connection getHBaseConnect() throws IOException {
	// 配置
    Configuration conf = HBaseConfiguration.create();
    conf.set("hbase.zookeeper.quorum", "127.0.0.1");
    conf.set("hbase.zookeeper.property.clientPort", "2181");
    conf.set("log4j.logger.org.apache.hadoop.hbase", "WARN");
    // 创建连接
    Connection connection = ConnectionFactory.createConnection(conf);
    return connection;
}

3.0 CREATE

// 创建表
public void createTable (String tableName,String columnFamily)  {
	try {
	// 获取连接,DDL操作需要获取Admin
        Connection hbaseConnect = hbase.getHBaseConnect();
        Admin admin = hbaseConnect.getAdmin();
        // 设置表名
        HTableDescriptor tableDescriptor = new HTableDescriptor(TableName.valueOf(tableName));
        // 设置列族
        tableDescriptor.addFamily(new HColumnDescriptor(columnFamily));
        // 创建表
        admin.createTable(tableDescriptor);
    } catch (IOException e) {
    	e.printStackTrace();
    }
}

3.1 INSERT

MySQL:

INSERT INTO ct_account_info_demo(account_id, account_owner , account_amount, is_deleted ) VALUES (?,?,?,?)

HBase реализует функции приведенных выше операторов SQL:

// 插入数据
public int insertAccount(Long accountId, String accountOwner, BigDecimal accountAmount) {
    String tableName = "ct_account_info_demo";		// 表名
    // 行键(为便于理解,这里将accountID作为RowKey,实际应用中RowKey的设计应该重点考虑)
    String rowKey = String.valueOf(accountId);
    String familyName = "account_info";				// 列族(在创建表时已定义)
    Map<String,String> columns = new HashMap<>();	 // 多个列
    columns.put("account_id",String.valueOf(accountId));
    columns.put("account_owner",accountOwner);
    columns.put("account_amount",String.valueOf(accountAmount));
    columns.put("is_deleted","n");
    updateColumnHBase(tableName,rowKey,familyName,columns);	// 更新HBase数据
    return 0;
}

private void updateColumnHBase(String tableName, String rowKey, String familyColumn, Map<String,String> columns) {
    try {
        Connection hbaseConnect = hbase.getHBaseConnect();	        // 获取HBase连接
        Table table = hbaseConnect.getTable(TableName.valueOf(tableName));   // 获取相应的表
        Put put = new Put(Bytes.toBytes(rowKey));	        		// 封装Put对象
        for (Map.Entry<String, String> entry : columns.entrySet()) {
            put.addColumn(Bytes.toBytes(familyColumn), Bytes.toBytes(entry.getKey()),
            Bytes.toBytes(entry.getValue()));
        }
        table.put(put);	        // 提交数据
        table.close();
    } catch (IOException e) {
    	e.printStackTrace();
    }
}

3.2 SELECT

MySQL:

SELECT * from ct_account_info_demo WHERE account_id = #{account_id}

HBase реализует функции приведенных выше операторов SQL:

// 读取数据
public Account getAccountInfoByID(Long accountId) {
     Account account = new Account();
     String tableName = "ct_account_info_demo";		// 表名
     String familyName = "account_info";			// 列族
     String rowKey = String.valueOf(accountId);		// 行键
     List<String> columns = new ArrayList<>();		// 设置需要返回哪些列
     columns.add("account_id");
     columns.add("account_owner");
     columns.add("account_amount");
     columns.add("is_deleted");
     // 获取某一行指定列的数据
     HashMap<String,String> accountRecord = getColumnHBase(tableName, rowKey,familyName,columns);
     if (accountRecord.size()==0) {
     	return null;
     }
     // 根据查询结果,封装账户信息
     account.setId( Long.valueOf(accountRecord.get("account_id")));
     account.setOwner(accountRecord.get("account_owner"));
     account.setBalance(new BigDecimal(accountRecord.get("account_amount")));
     account.setDeleted(accountRecord.get("isDeleted"));
     return account;
}
 
private HashMap<String, String> getColumnHBase(String tableName, String rowKey, String familyColumn, List<String> columns) {
     HashMap<String,String> accountRecord = new HashMap<>(16);
     try {
         Connection hbaseConnect = hbase.getHBaseConnect();		// 获取HBase连接
         Table table = hbaseConnect.getTable(TableName.valueOf(tableName));	// 获取相应的表
         Get get = new Get(Bytes.toBytes(rowKey));				// 封装Get对象
         for (String column:columns) {
             get.addColumn(Bytes.toBytes(familyColumn), Bytes.toBytes(column));
         }
         Result result = table.get(get);		// 获取数据
         if (result.listCells() != null) {
             for (Cell cell : result.listCells()) {
                 String k = Bytes.toString(cell.getQualifierArray(), cell.getQualifierOffset(), cell.getQualifierLength());
                 String v = Bytes.toString(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength());
                 accountRecord.put(k,v);	// 将结果存放在map中
             }
         }
         table.close();
     } catch (IOException e) {
     e.printStackTrace();
     }
     return accountRecord;		// 返回本次查询的结果
}

3.3 UPDATE

MySQL:

UPDATE ct_account_info_demo SET account_amount = account_amount + #{transAmount} WHERE account_id = #{fromAccountId}

HBase реализует функции приведенных выше операторов SQL:

// 更新数据
public void transIn(Long accountId, BigDecimal accountAmount) {
    String tableName = "ct_account_info_demo";		// 表名
    String rowKey = String.valueOf(accountId);		// 行键
    String familyName = "account_info";				// 列族
    List<String> columns = new ArrayList<>();		// 获取账户信息
    columns.add("account_amount");
    HashMap<String,String> accountRecord = getColumnHBase(tableName, rowKey,familyName,columns);
    // 增加账户余额
    BigDecimal newAccountAmount = new BigDecimal(accountRecord.get("account_amount")).add(accountAmount);
    // 更新账户的余额
    Map<String,String> fromColumns = new HashMap<>(1);
    fromColumns.put("account_amount",String.valueOf(newAccountAmount));
    // 更新HBase数据
    updateColumnHBase(tableName,rowKey,familyName,fromColumns);
}

3.4 DELETE

MySQL:

DELETE FROM ct_account_info_demo WHERE account_id = ?

Функции приведенных выше операторов SQL реализованы через HBase:

// 删除数据
public void deleteAccount (String tableName, Long accountId) {
    try {
        Connection hbaseConnect = hbase.getHBaseConnect();
        // 行键
        String rowKey = String.valueOf(accountId);
        // 列族
        String familyName = "account_info";
        Table table = hbaseConnect.getTable(TableName.valueOf(tableName));
        Delete delete = new Delete(Bytes.toBytes(rowKey));
        // 删除该行指定列的数据
        delete.deleteColumn(Bytes.toBytes(familyName), Bytes.toBytes("account_id"));
        delete.deleteColumn(Bytes.toBytes(familyName), Bytes.toBytes("account_owner"));
        delete.deleteColumn(Bytes.toBytes(familyName), Bytes.toBytes("account_amount"));
        delete.deleteColumn(Bytes.toBytes(familyName), Bytes.toBytes("is_deleted"));
        // 删除整个列族
        //delete.deleteFamily(Bytes.toBytes(familyName));
        table.delete(delete);
        table.close();
    } catch (IOException e) {
    	e.printStackTrace();
    }
}

3.5 LIKE

MySQL:

SELECT * FROM ct_account_info_demo WHERE account_id = #{account_id} AND account_owner LIKE CONCAT('%', #{keyWord}, '%')

HBase реализует функции приведенных выше операторов SQL:

// 模糊查询
public Account getAccountInfoByKeyWord(Long accountId, String keyWord) {
    Account account = new Account();
    // 表名
    String tableName = "ct_account_info_demo";		
    // 起始行键(闭区间)
    String startRow = String.valueOf(accountId);	
    // 终止行键(开区间,结果不包含stopRow)
    String stopRow = String.valueOf(accountId);	
    // 列族
    String familyName = "account_info";
    // 设置需要模糊查询的列
    String targetColumn = "account_owner";
    // 设置需要返回哪些列
    List<String> columns = new ArrayList<>();
    columns.add("account_id");
    columns.add("account_owner");
    columns.add("account_amount");
    columns.add("is_deleted");
    // 模糊查询
    HashMap<String,String> accountRecord = singleColumnFilter(tableName, familyName, startRow, stopRow, targetColumn, keyWord, columns);
    if (accountRecord.size()==0) {
    	return null;
    }
    // 根据查询结果,封装账户信息
    account.setId( Long.valueOf(accountRecord.get("account_id")));
    account.setOwner(accountRecord.get("account_owner"));
    account.setBalance(new BigDecimal(accountRecord.get("account_amount")));
    account.setDeleted(accountRecord.get("isDeleted"));
    return account;
}

private HashMap<String,String> singleColumnFilter(String tableName, String familyColumn, String startRowKey, String stopRowKey, String targetColumn, String keyWord, List<String> columns) {
    if (hbase == null) {
    	throw new NullPointerException("HBaseConfig");
    }
    if (familyColumn == null || columns.size() == 0) {
    	return null;
    }
    HashMap<String,String> accountRecord = new HashMap<>(8);
    try {
        // 获取HBase连接
        Connection hbaseConnect = hbase.getHBaseConnect();
        // 获取相应的表
        Table table = hbaseConnect.getTable(TableName.valueOf(tableName));
        // 封装Scan
        Scan scan = new Scan();
        scan.setStartRow(Bytes.toBytes(startRowKey));
        scan.setStopRow(Bytes.toBytes(stopRowKey));
        // 设置查询的列
        for (String column:columns) {
            scan.addColumn(Bytes.toBytes(familyColumn), Bytes.toBytes(column));
        }
        // 定义过滤器:某一列的值是否包含关键字
        SingleColumnValueFilter singleColumnValueFilter = new SingleColumnValueFilter(Bytes.toBytes(familyColumn),Bytes.toBytes(targetColumn),CompareFilter.CompareOp.EQUAL,new SubstringComparator(keyWord));
        //ValueFilter filter = new ValueFilter(CompareFilter.CompareOp.EQUAL, new SubstringComparator(keyWord));
        FilterList list = new FilterList(FilterList.Operator.MUST_PASS_ONE,singleColumnValueFilter);
        // Scan添加过滤器
        scan.setFilter(list);
        // 获取数据
        ResultScanner resultScanner = table.getScanner(scan);
        for(Result result = resultScanner.next();result!=null;result = resultScanner.next()){
        	if (result.listCells() != null) {
            	for (Cell cell : result.listCells()) {
                    // 将结果存放在map中
                    String k = Bytes.toString(cell.getQualifierArray(), cell.getQualifierOffset(), cell.getQualifierLength());
                    String v = Bytes.toString(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength());
                    accountRecord.put(k,v);
    			}
    		}
    	}
    	table.close();
    } catch (IOException e) {
    	e.printStackTrace();
    }
    // 返回所有行数据
    return accountRecord;
}

Послесловие:

В школе я работал над проектами, связанными с Elasticsearch. Разбираясь в HBase, я обнаружил, что дизайн HBase на самом деле очень похож на дизайн Elasticsearch, например, дизайн механизма HBase Flush&Compact точно такой же, как у Elasticsearch, поэтому его относительно легко понять.

По сути, HBase позиционируется как распределенная система хранения, а Elasticsearch — как распределенная поисковая система, они не эквивалентны, но дополняют друг друга. HBase имеет ограниченные возможности поиска и поддерживает только индексы на основе RowKey. Расширенные функции, такие как другие вторичные индексы, необходимо разрабатывать самостоятельно. Поэтому есть несколько случаев объединения HBase и Elasticsearch для достижения возможностей хранения и поиска. Восполнить недостаток емкости хранилища Elasticsearch можно с помощью HBase, а недостаток емкости поиска HBase — с помощью Elasticsearch.

На самом деле, это не только HBase и Elasticsearch. Распределенная структура или система любого типа, все они имеют определенные общие черты, разница заключается в их соответствующих задачах. Я считаю, что при изучении распределенного ПО промежуточного слоя вы должны сначала прояснить его основные проблемы, а затем сравнить с другим ПО промежуточного слоя, выделить общие черты и характеристики и еще больше углубить свое понимание.

Использованная литература: