Как создать идентификаторы автоинкремента в Кассандре
Мы знаем, что легко создавать идентификаторы автоинкремента в базах данных SQL, есть ли хорошее решение для этого в Cassandra? Идентификаторы должны быть для ключа или имени столбца.
8 ответов
Как насчет следующего, используя легкие транзакции Кассандры
1 - Создать таблицу идентификаторов:
CREATE TABLE ids (
id_name varchar,
next_id int,
PRIMARY KEY (id_name)
)
2 - Вставьте каждый идентификатор, с которым вы хотите использовать глобальную последовательность
Например:
INSERT INTO ids (id_name, next_id)
VALUES ('person_id', 1)
3 - Затем при вставке в таблицу, где вы хотите использовать автоинкрементный ключ, сделайте следующее:
3.1 - Получить next_id из таблицы идентификаторов:
SELECT next_id FROM ids WHERE id_name = 'person_id'
Допустим, результат следующий_ид = 1
3.2 - Увеличить next_id следующим образом:
UPDATE ids SET next_id = 2 WHERE id_name = 'person_id' IF next_id = 1
Результат должен выглядеть так:
[{[applied]: True}]
Если он был успешно обновлен, ИЛИ
[{[applied]: False, next_id: 2}]
Если кто-то уже обновил его.
Так что, если вы получили True, используйте идентификатор "1" - он ваш. В противном случае увеличьте значение next_id (или просто используйте возвращенный next_id) и повторите процесс.
Создание глобальной последовательной последовательности чисел не имеет никакого смысла в распределенной системе. Используйте UUID.
(Потому что вы должны были бы заставить всех участников согласиться и принять эволюцию последовательности - при наивной реализации)
Там нет хорошего решения.
- Создайте столбец с номером, увеличьте номер и сохраните его во всех репликах вместе с временным идентификатором, прочитайте все реплики и проверьте, является ли временный идентификатор "вашим", если не сделайте это снова... не является хорошим решением и не будет масштаб.
или же
- Создайте свой собственный сервис идентификации, где вы получите свой следующий идентификатор. Эта служба будет работать только в одном экземпляре и будет не масштабирующим страшным фактором.
Как только что-то выходит за пределы одного экземпляра, последовательность идентификаторов усложняется, по крайней мере, если вы хотите, чтобы она масштабировалась. Это включает в себя реляционные базы данных.
Существует тип данных счетчика, который можно использовать. Рассмотрим приведенный ниже пример.
CREATE KEYSPACE counterks WITH REPLICATION =
{ 'class' : 'NetworkTopologyStrategy', 'datacenter1' : 3 };
Создайте таблицу для столбца счетчика.
CREATE TABLE counterks.page_view_counts
(counter_value counter,
url_name varchar,
page_name varchar,
PRIMARY KEY (url_name, page_name)
);
Загрузите данные в столбец счетчика.
UPDATE counterks.page_view_counts
SET counter_value = counter_value + 1
WHERE url_name='www.datastax.com' AND page_name='home';
Посмотрите на значение счетчика.
SELECT * FROM counterks.page_view_counts;
Выход:
url_name | page_name | counter_value
------------------+-----------+---------------
www.datastax.com | home | 1
Увеличьте значение счетчика.
UPDATE counterks.page_view_counts
SET counter_value = counter_value + 2
WHERE url_name='www.datastax.com' AND page_name='home';
Посмотрите на значение счетчика.
url_name | page_name | counter_value
------------------+-----------+---------------
www.datastax.com | home | 3
Обратитесь к этому для получения дополнительной информации: http://docs.datastax.com/en/cql/3.1/cql/cql_using/use_counter_t.html
Я думаю, что ИМХО ожидать, что Кассандра предоставит поле с автоинкрементом, НЕПРАВИЛЬНО
Cassandra - это элегантная децентрализованная база данных, поэтому ожидается, что она предоставит поле автоинкремента, облагая налогом и опровергая первоначальную цель, потому что это значение затем должно поддерживаться в центральном месте
Следовательно, не принимайте решения, какая база данных основана на автоматическом увеличении числа
Вместо этого сгенерируйте идентификатор в коде или службе в вашем приложении, которые могут продолжать генерировать случайные уникальные идентификаторы и использовать их для применения к вашей модели данных, таким образом цель и преимущества Cassandra не будут побеждены
Этот вопрос довольно старый, но я хотел бы дополнить его другим решением.
Любое решение, основанное на синхронизации узлов, нецелесообразно. Это почти наверняка сломать, блокируя генерацию идентификаторов или создавая дубликаты идентификаторов.
MySQL способ
Вы можете воспроизвести способ репликации мастер-мастер mysql с помощью auto_increment_increment
а также auto_increment_offset
параметры.
Чтобы воспроизвести его, вам нужно знать количество узлов или максимальное число ожидаемых узлов, а также вам нужно создать (не-кассандровый) счетчик (файл для примера) на каждом узле.
Каждый раз, когда вы хотите сгенерировать новое число, вы находите текущее значение, добавляете приращение и сохраняете его. Если это еще не существует, это смещение.
Таким образом, для 10 узлов вы будете иметь приращение 10 и смещение 1 для первого узла, 2 для второго узла и т. Д. Узел 1 будет создавать идентификаторы 1, 11, 21. Узел 2 будет создавать идентификаторы 2, 21, 22.
Если вы хотите, чтобы ваши идентификаторы были (приблизительно) упорядочены между узлами, вам необходимо поддерживать общий счетчик и убедиться, что каждый сгенерированный идентификатор выше, чем общий счетчик. Таким образом, если ваши узлы / центры обработки данных не синхронизированы в течение длительного времени, вы не должны заметить большой разницы.
Приставка
Вы можете сделать в основном то же самое, добавив префикс ID (если это приемлемое решение) к номеру узла (или имени). И вам не нужно знать количество узлов. Узел 1 будет создавать 1_1, 1_2, 1_3. Узел 2 создаст 2_1, 2_2, 2_3.
Изменить: это решение не является правильным. Смотрите первый комментарий.
Мое решение:
1 - Создать таблицу идентификаторов:
CREATE TABLE ids (
id_name varchar,
next_id counter,
PRIMARY KEY (id_name)
)
2 - Вставляя в таблицу, где вы хотите использовать автоинкрементный ключ, сделайте следующее:
2.1 - Счетчик приращений (он будет создан, если не существует), используя самый высокий уровень согласованности
UPDATE ids
SET next_id = next_id + 1
WHERE id_name = $AUTO_INCREMENTED_ID
USING CONSISTENCY ALL
2.2 - Получить новое значение идентификатора:
SELECT next_id
FROM ids
WHERE id_name = $AUTO_INCREMENTED_ID
2.3 - Вставьте значение с автоматически увеличенным идентификатором
INSERT INTO some_table ($AUTO_INCREMENTED_ID, ...)
VALUES ($RESULT_FROM_PREVIOUS_QUERY, ...)
Слова, начинающиеся с '$' в моем ответе, говорят сами за себя (я надеюсь) заполнители...
Конечно, это не рекомендуемый метод. Используйте его, только если вам нужно.
Они действительно должны быть последовательными, или вам просто нужно подсчитать числа, которые намного меньше, чем UUID, который легко вводится человеком?
Если вам действительно нужны последовательные номера, то вам нужно будет выполнить одно из следующих действий.
Иметь таблицу в Кассандре, где ключ /id - это поле для генератора, а значение - это число... делайте условные обновления в цикле, пока вы успешно не увеличите счет. (плохая идея)
Есть служба генератора, которая даст вам следующий номер. Это может выполняться только в одной системе и быть единственной точкой отказа, но в зависимости от ваших потребностей это может быть лучше.
В качестве альтернативы... Аналогично первому, но получайте партии по 100 или более номеров за раз и раздайте их внутри вашего процесса / потока... Это будет иметь меньше разногласий, но не гарантирует последовательный порядок, только уникальность.. Если вам нужны только короткие номера, которые являются уникальными для отображения, это может быть вашим лучшим выбором.