Рубрики
Без рубрики

Руководство по CockroachDB на Java

Узнайте, как настроить, отслеживать и взаимодействовать с экземпляром CockroachDB с помощью JDBC.

Автор оригинала: baeldung.

1. введение

Этот учебник представляет собой вводное руководство по использованию CockroachDB с Java.

Мы объясним ключевые функции, как настроить локальный кластер и как его контролировать, а также практическое руководство о том, как мы можем использовать Java для подключения и взаимодействия с сервером.

Давайте начнем с определения того, что это такое.

2. Таракан.

CockroachDB-это распределенная база данных SQL, построенная поверх транзакционного и согласованного хранилища ключей и значений.

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

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

2.1. Основные характеристики

Давайте продолжим изучение некоторых ключевых аспектов TockroachDB:

  • Совместимость с SQL API и PostgreSQL – для структурирования, обработки и запроса данных
  • Транзакции ACID – поддержка распределенных транзакций и обеспечение высокой согласованности
  • Облачная готовность -предназначена для работы в облаке или локальном решении, обеспечивающем легкую миграцию между различными облачными поставщиками без каких – либо перерывов в обслуживании
  • Масштабирование по горизонтали – добавление емкости так же просто, как указание нового узла на работающий кластер с минимальными затратами оператора
  • Репликация – реплицирует данные для обеспечения доступности и гарантирует согласованность между репликами
  • Автоматическое восстановление – продолжайте без проблем, пока большинство реплик остаются доступными для краткосрочных сбоев, в то время как для долгосрочных сбоев автоматически перебалансирует реплики с отсутствующих узлов, используя незатронутые реплики в качестве источников

3. Настройка базы данных тараканов

После того , как мы установили CockroachDB , мы можем запустить первый узел нашего локального кластера:

cockroach start --insecure --host=localhost;

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

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

cockroach start --insecure --store=node2 \
  --host=localhost --port=26258 --http-port=8081 \
  --join=localhost:26257;

cockroach start --insecure --store=node3 \
  --host=localhost --port=26259 --http-port=8082 \
  --join=localhost:26257;

Для двух дополнительных узлов мы использовали флаг join для подключения новых узлов к кластеру, указав адрес и порт первого узла, в нашем случае localhost:26257. Каждому узлу в локальном кластере требуются уникальные значения store , port и http-port .

При настройке распределенного кластера CockroachDB каждый узел будет находиться на другой машине, поэтому указания порта , хранилища и http-порта можно избежать, поскольку значений по умолчанию достаточно. Кроме того, фактический IP-адрес первого узла должен использоваться при присоединении дополнительных узлов к кластеру.

3.1. Настройка базы данных и пользователя

Как только наш кластер будет запущен и запущен, с помощью консоли SQL, поставляемой с CockroachDB, нам нужно создать нашу базу данных и пользователя.

Прежде всего, давайте запустим консоль SQL:

cockroach sql --insecure;

Теперь давайте создадим нашу базу данных testdb , создадим пользователя и добавим ему гранты, чтобы он мог выполнять операции CRUD:

CREATE DATABASE testdb;
CREATE USER user17 with password 'qwerty';
GRANT ALL ON DATABASE testdb TO user17;

Если мы хотим убедиться, что база данных была создана правильно, мы можем перечислить все базы данных, созданные в текущем узле:

SHOW DATABASES;

Наконец, если мы хотим проверить функцию автоматической репликации CockroachDB, мы можем проверить на одном из двух других узлов, правильно ли была создана база данных. Для этого мы должны указать флаг port при использовании консоли SQL:

cockroach sql --insecure --port=26258;

4. Мониторинг тараканов.

Теперь, когда мы запустили наш локальный кластер и создали базу данных, мы можем отслеживать их с помощью пользовательского интерфейса администратора CockroachDB :

Этот пользовательский интерфейс администратора, который поставляется в комплекте с CockroachDB, можно получить по адресу http://localhost:8080 как только кластер будет запущен и запущен. В частности, он предоставляет подробную информацию о конфигурации кластера и базы данных, а также помогает нам оптимизировать производительность кластера, отслеживая такие показатели, как :

  • Состояние кластера – основные показатели состояния кластера
  • Метрики времени выполнения – метрики о количестве узлов, времени процессора и использовании памяти
  • Производительность SQL – метрики о соединениях SQL, запросах и транзакциях
  • Сведения о репликации – метрики о том, как данные реплицируются в кластере
  • Сведения об узлах – сведения о живых, мертвых и выведенных из эксплуатации узлах
  • Сведения о базе данных – сведения о системных и пользовательских базах данных в кластере

5. Настройка проекта

Учитывая, что у нас работает локальный кластер CockroachDB, чтобы иметь возможность подключиться к нему, мы должны добавить дополнительную зависимость к нашему pom.xml:


    org.postgresql
    postgresql
    42.1.4

Или для проекта Gradle:

compile 'org.postgresql:postgresql:42.1.4'

6. Использование TockroachDB

Теперь, когда ясно, с чем мы работаем и что все настроено правильно, давайте начнем использовать его.

Благодаря совместимости с PostgreSQL можно либо напрямую подключиться к JDBC, либо использовать ORM, например Hibernate (На момент написания статьи (январь 2018 года) оба драйвера были протестированы достаточно, чтобы претендовать на поддержку бета-уровня по словам разработчиков). В нашем случае мы будем использовать JDBC для взаимодействия с базой данных.

Для простоты мы рассмотрим основные операции CRUD, поскольку они лучше всего подходят для начала.

Давайте начнем с подключения к базе данных.

6.1. Подключение к базе данных тараканов

Чтобы открыть соединение с базой данных, мы можем использовать метод getConnection() класса DriverManager . Для этого метода требуется URL-адрес подключения Строка параметр, имя пользователя и пароль:

Connection con = DriverManager.getConnection(
  "jdbc:postgresql://localhost:26257/testdb", "user17", "qwerty"
);

6.2. Создание таблицы

С рабочим подключением мы можем начать создавать таблицу articles , которую мы будем использовать для всех операций CRUD:

String TABLE_NAME = "articles";
StringBuilder sb = new StringBuilder("CREATE TABLE IF NOT EXISTS ")
  .append(TABLE_NAME)
  .append("(id uuid PRIMARY KEY, ")
  .append("title string,")
  .append("author string)");

String query = sb.toString();
Statement stmt = connection.createStatement();
stmt.execute(query);

Если мы хотим убедиться, что таблица была создана правильно, мы можем использовать команду ПОКАЗАТЬ ТАБЛИЦЫ :

PreparedStatement preparedStatement = con.prepareStatement("SHOW TABLES");
ResultSet resultSet = preparedStatement.executeQuery();
List tables = new ArrayList<>();
while (resultSet.next()) {
    tables.add(resultSet.getString("Table"));
}

assertTrue(tables.stream().anyMatch(t -> t.equals(TABLE_NAME)));

Давайте посмотрим, как можно изменить только что созданную таблицу.

6.3. Изменение таблицы

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

StringBuilder sb = new StringBuilder("ALTER TABLE ").append(TABLE_NAME)
  .append(" ADD ")
  .append(columnName)
  .append(" ")
  .append(columnType);

String query = sb.toString();
Statement stmt = connection.createStatement();
stmt.execute(query);

После того, как мы изменили таблицу, мы можем проверить, был ли добавлен новый столбец, используя команду ПОКАЗАТЬ СТОЛБЦЫ ИЗ :

String query = "SHOW COLUMNS FROM " + TABLE_NAME;
PreparedStatement preparedStatement = con.prepareStatement(query);
ResultSet resultSet = preparedStatement.executeQuery();
List columns = new ArrayList<>();
while (resultSet.next()) {
    columns.add(resultSet.getString("Field"));
}

assertTrue(columns.stream().anyMatch(c -> c.equals(columnName)));

6.4. Удаление таблицы

При работе с таблицами иногда нам нужно удалить их, и это может быть легко достигнуто с помощью нескольких строк кода:

StringBuilder sb = new StringBuilder("DROP TABLE IF EXISTS ")
  .append(TABLE_NAME);

String query = sb.toString();
Statement stmt = connection.createStatement();
stmt.execute(query);

6.5. Вставка Данных

Как только мы очистим операции, которые могут быть выполнены над таблицей, теперь мы можем начать работать с данными. Мы можем начать определять класс Article :

public class Article {

    private UUID id;
    private String title;
    private String author;

    // standard constructor/getters/setters
}

Теперь мы можем увидеть, как добавить Статью в нашу статьи таблицу:

StringBuilder sb = new StringBuilder("INSERT INTO ").append(TABLE_NAME)
  .append("(id, title, author) ")
  .append("VALUES (?,?,?)");

String query = sb.toString();
PreparedStatement preparedStatement = connection.prepareStatement(query);
preparedStatement.setString(1, article.getId().toString());
preparedStatement.setString(2, article.getTitle());
preparedStatement.setString(3, article.getAuthor());
preparedStatement.execute();

6.6. Считывание Данных

Как только данные будут сохранены в таблице, мы хотим прочитать эти данные, и это может быть легко достигнуто:

StringBuilder sb = new StringBuilder("SELECT * FROM ")
  .append(TABLE_NAME);

String query = sb.toString();
PreparedStatement preparedStatement = connection.prepareStatement(query);
ResultSet rs = preparedStatement.executeQuery();

Однако, если мы не хотим читать все данные внутри таблицы articles , а только одну Article , мы можем просто изменить способ построения нашего PreparedStatement :

StringBuilder sb = new StringBuilder("SELECT * FROM ").append(TABLE_NAME)
  .append(" WHERE title = ?");

String query = sb.toString();
PreparedStatement preparedStatement = connection.prepareStatement(query);
preparedStatement.setString(1, title);
ResultSet rs = preparedStatement.executeQuery();

6.7. Удаление Данных

И последнее, но не менее важное: если мы хотим удалить данные из нашей таблицы, мы можем удалить ограниченный набор записей с помощью стандартной команды УДАЛИТЬ ИЗ :

StringBuilder sb = new StringBuilder("DELETE FROM ").append(TABLE_NAME)
  .append(" WHERE title = ?");

String query = sb.toString();
PreparedStatement preparedStatement = connection.prepareStatement(query);
preparedStatement.setString(1, title);
preparedStatement.execute();

Или мы можем удалить все записи в таблице с помощью функции TRUNCATE :

StringBuilder sb = new StringBuilder("TRUNCATE TABLE ")
  .append(TABLE_NAME);

String query = sb.toString();
Statement stmt = connection.createStatement();
stmt.execute(query);

6.8. Обработка Транзакций

После подключения к базе данных по умолчанию каждая отдельная инструкция SQL обрабатывается как транзакция и автоматически фиксируется сразу после завершения ее выполнения.

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

Сначала нам нужно отключить режим автоматической фиксации, установив свойство autoCommit для Connection в false , а затем использовать методы commit() и rollback() для управления транзакцией.

Давайте посмотрим, как мы можем добиться согласованности данных при выполнении нескольких вставок:

try {
    con.setAutoCommit(false);

    UUID articleId = UUID.randomUUID();

    Article article = new Article(
      articleId, "Guide to CockroachDB in Java", "baeldung"
    );
    articleRepository.insertArticle(article);

    article = new Article(
      articleId, "A Guide to MongoDB with Java", "baeldung"
    );
    articleRepository.insertArticle(article); // Exception

    con.commit();
} catch (Exception e) {
    con.rollback();
} finally {
    con.setAutoCommit(true);
}

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

7. Заключение

В этой статье мы объяснили, что такое CockroachDB, как настроить простой локальный кластер и как мы можем взаимодействовать с ним с Java.

Полный исходный код этой статьи можно найти, как всегда, на Github .