ClickHouse/dbms/include/DB/Databases/DatabaseCloud.h
2017-03-13 21:01:46 +03:00

151 lines
8.0 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#pragma once
#include <DB/Databases/IDatabase.h>
#include <DB/Common/UInt128.h>
#include <DB/Storages/IStorage.h>
namespace Poco { class Logger; }
namespace DB
{
/** Позволяет создавать "облачные таблицы".
* Список таких таблиц хранится в ZooKeeper.
* Все серверы, ссылающиеся на один путь в ZooKeeper, видят один и тот же список таблиц.
* CREATE, DROP, RENAME атомарны.
*
* Для БД задаётся уровень репликации N.
* При записи в "облачную" таблицу, некоторым образом выбирается N живых серверов в разных датацентрах,
* на каждом из них создаётся локальная таблица, и в них производится запись.
*
* Движок имеет параметры: Cloud(zookeeper_path, replication_factor, datacenter_name)
* Пример: Cloud('/clickhouse/clouds/production/', 3, 'FIN')
*
* Структура в ZooKeeper:
*
* cloud_path - путь к "облаку"; может существовать несколько разных независимых облаков
/table_definitions - множество уникальных определений таблиц, чтобы не писать их много раз для большого количества таблиц
/hash128 -> sql - отображение: хэш от определения таблицы (идентификатор) -> само определение таблицы в виде CREATE запроса
/tables - список таблиц
/database_name - имя базы данных
/name_hash_mod -> compressed_table_list
- список таблиц сделан двухуровневым, чтобы уменьшить количество узлов в ZooKeeper при наличии большого количества таблиц
- узлы создаются для каждого остатка от деления хэша от имени таблицы, например, на 4096
- и в каждом узле хранится список таблиц (имя таблицы, имя локальной таблицы, хэш от структуры, список хостов) в сжатом виде
/local_tables - список локальных таблиц, чтобы по имени локальной таблицы можно было определить её структуру
/database_name
/name_hash_mod -> compressed_table_list
- список пар (хэш от имени таблицы, хэш от структуры) в сжатом виде
/locality_keys - сериализованный список ключей локальности в порядке их появления
- ключ локальности - произвольная строка
- движок БД определяет серверы для расположения данных таким образом,
чтобы, при одинаковом множестве живых серверов,
одному ключу локальности соответствовала одна группа из N серверов для расположения данных.
/nodes - список серверов, на которых зарегистрированы облачные БД с таким путём в ZK
/hostname - имя хоста
TODO /alive - эфемерная нода для предварительной проверки живости
/datacenter - имя датацентра
TODO /disk_space
* К одному облаку может относиться несколько БД, названных по-разному. Например, БД hits и visits могут относиться к одному облаку.
*/
class DatabaseCloud : public IDatabase
{
private:
const String name;
const String data_path;
String zookeeper_path;
const size_t replication_factor;
const String hostname;
const String datacenter_name;
using Logger = Poco::Logger;
Logger * log;
Context & context;
/** Локальные таблицы - это таблицы, находящиеся непосредственно на локальном сервере.
* Они хранят данные облачных таблиц: облачная таблица представлена несколькими локальными таблицами на разных серверах.
* Эти таблицы не видны пользователю при перечислении таблиц, хотя доступны при обращении по имени.
* Имя локальных таблиц имеет специальную форму, например, начинаться на _local, чтобы они не путались с облачными таблицами.
* Локальные таблицы загружаются лениво, при первом обращении.
*/
Tables local_tables_cache;
mutable std::mutex local_tables_mutex;
friend class DatabaseCloudIterator;
public:
DatabaseCloud(
bool attach,
const String & name_,
const String & zookeeper_path_,
size_t replication_factor_,
const String & datacenter_name_,
Context & context_);
String getEngineName() const override { return "Cloud"; }
void loadTables(Context & context, ThreadPool * thread_pool, bool has_force_restore_data_flag) override;
bool isTableExist(const String & table_name) const override;
StoragePtr tryGetTable(const String & table_name) override;
DatabaseIteratorPtr getIterator() override;
bool empty() const override;
void createTable(
const String & table_name, const StoragePtr & table, const ASTPtr & query, const String & engine, const Settings & settings) override;
void removeTable(const String & table_name) override;
void attachTable(const String & table_name, const StoragePtr & table) override;
StoragePtr detachTable(const String & table_name) override;
void renameTable(
const Context & context, const String & table_name, IDatabase & to_database, const String & to_table_name, const Settings & settings) override;
time_t getTableMetadataModificationTime(const String & name) override;
ASTPtr getCreateQuery(const String & table_name) const override;
void shutdown() override;
void drop() override;
void alterTable(
const Context & context,
const String & name,
const NamesAndTypesList & columns,
const NamesAndTypesList & materialized_columns,
const NamesAndTypesList & alias_columns,
const ColumnDefaults & column_defaults,
const ASTModifier & engine_modifier) override
{
throw Exception("ALTER TABLE is not supported by database engine " + getEngineName(), ErrorCodes::NOT_IMPLEMENTED);
}
using Hash = UInt128;
private:
void createZookeeperNodes();
/// Получить имя узла, в котором будет храниться часть списка таблиц. (Список таблиц является двухуровневым.)
String getNameOfNodeWithTables(const String & table_name) const;
/// Хэшировать имя таблицы вместе с именем БД.
Hash getTableHash(const String & table_name) const;
/// Определения таблиц хранятся косвенным образом и адресуются своим хэшом. Вычислить хэш.
Hash getHashForTableDefinition(const String & definition) const;
/// Пойти в ZooKeeper и по хэшу получить определение таблицы.
String getTableDefinitionFromHash(Hash hash) const;
/// Определить серверы, на которых будут храниться данные таблицы.
std::vector<String> selectHostsForTable(const String & locality_key) const;
};
}