Поскольку работа требует использования 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, которая представляет собой концепцию «гибкой схемы».
- В размерности таблицы она содержит несколько строк, каждая строка отличается RowKey.
- В измерении строк оно содержит несколько семейств столбцов.Семейства столбцов аналогичны классификации столбцов, но это не просто логические понятия.Основное физическое хранилище также различается семействами столбцов (одно семейство столбцов соответствует одному магазину в разных регионах). ).
- В измерении семейства столбцов, содержащем несколько столбцов, столбцы являются динамическими. Это не столбец, а пара ключ-значение, где Key — это имя столбца, а Value — значение столбца.
Структура таблицы HBase выглядит следующим образом:
- RowKey (ключ строки): RowKey упорядочен по словарю, а HBase реализует индексирование на основе RowKey;
- Семейство столбцов: вертикальный разрез, в строке может быть несколько семейств столбцов, а в семействе столбцов может быть любое количество столбцов;
- Ключ-значение (пара ключ-значение): в каждом столбце хранится пара ключ-значение, ключ — это имя столбца, а значение — значение столбца;
- Байт (тип данных): данные хранятся в байтах в HBase, а фактический тип данных преобразуется пользователем;
- Версия (мультиверсия): каждый столбец может быть настроен с соответствующей версией для получения данных указанной версии (по умолчанию возвращается последняя версия);
- Разреженная матрица: количество столбцов может варьироваться от строки к строке, но место для хранения занимают только фактические столбцы.
1.3 Region
Как HBase управляет данными? (физический слой)
Регион — это понятие в HBase, аналогичное разделу в СУБД.
- Регион — это горизонтальный срез таблицы.Таблица состоит из одного или нескольких регионов, и регионы назначаются каждому серверу регионов;
- Регион разделен на несколько Stores в соответствии с семейством столбцов, каждое Store состоит из MemStore и StoreFile; данные записываются в MemStore, MemStore аналогичен входному буферу, который после сохранения является StoreFile; журнал WAL обновляется одновременно по мере записи данных и использования WAL для восстановления после сбоя для обеспечения безопасности чтения и записи данных;
- 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: время запуска регионального сервера, на котором находится регион.
Процесс записи данных:
Содержание данных необходимо указывать, когда данные написаны.
- Клиент HBase обращается к ZooKeeper, получает адрес hbase:meta и кэширует этот адрес;
- Получите доступ к hbase:meta соответствующего регионального сервера;
- Получите адрес сервера региона, соответствующий RowKey, из таблицы hbase:meta и кэшируйте адрес;
- Клиент HBase напрямую запрашивает региональный сервер для завершения чтения и записи данных в соответствии с адресом.
Примечание 1. Маршрутизация данных не требует участия Мастера, что означает, что операция DML не требует участия Мастера. С помощью hbase:meta клиент напрямую связывается с сервером регионов для маршрутизации, чтения и записи данных.
Примечание 2. После того, как клиент получит адрес hbase:meta, он кэширует информацию об адресе, чтобы уменьшить доступ к ZooKeeper. В то же время клиент ищет hbase:meta по RowKey, и после получения соответствующего адреса Region Server он также кэширует адрес, чтобы уменьшить доступ к hbase:meta. Поскольку таблица hbase:meta хранится на региональном сервере, ее размер может быть большим, поэтому полное содержимое hbase:meta не будет кэшироваться.
1.5 Применимые сценарии HBase
- Приложения, не требующие сложных запросов. HBase изначально поддерживает только индексы на основе RowKey. Для некоторых сложных запросов (таких как нечеткие запросы, запросы с несколькими полями) HBase может потребоваться полное сканирование таблицы для получения результатов.
- Приложения, требующие интенсивной записи. HBase — это система, которая быстро пишет и медленно читает (медленность относительная). HBase разработан на основе Google BigTable, и типичное приложение предназначено для непрерывной вставки новых данных (например, информации о веб-странице Google).
- Приложения с низкими требованиями к транзакциям. HBase поддерживает только транзакции на основе RowKey.
- Приложения, требующие высокой производительности и надежности. HBase не имеет единой точки отказа и обеспечивает высокую доступность.
- Приложения с особенно большим объемом данных. 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 и семейство столбцов при вставке данных).
В основном,
- HBase имеет больше концепций RowKey и Column Family, чем MySQL.RowKey здесь похож на первичный ключ в MySQL, а Column Family эквивалентен «классификации» нескольких столбцов.
- Когда имеется только одно семейство столбцов, схема HBase и MySQL может быть согласованной, но HBase позволяет некоторым полям быть пустыми или динамически добавлять столбец, в то время как MySQL может только заполнять соответствующий столбец в соответствии со схемой и не может динамически увеличиваться или увеличиваться. уменьшить столбцы.
- Поскольку схема 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. Распределенная структура или система любого типа, все они имеют определенные общие черты, разница заключается в их соответствующих задачах. Я считаю, что при изучении распределенного ПО промежуточного слоя вы должны сначала прояснить его основные проблемы, а затем сравнить с другим ПО промежуточного слоя, выделить общие черты и характеристики и еще больше углубить свое понимание.