TTL означает «Время жить». Это обычная функциональность, предоставляемая многими БД нового поколения.

Современные БД предназначены для скорости и масштабирования, и многие из них имеют некоторые ограничения для достижения этого, почти все основные БД Nosql отказываются от объединений, чтобы обеспечить более быструю и масштабируемую систему сохранения. Большая часть их расширяемых функций находится на начальной стадии. Триггеры, хранимые процедуры, представления, функции, сеансы, CDC и т. Д.

Однако большинство из них предоставляют способы или альтернативные способы поддержки некоторых из этих функций. TTL - один из таких инструментов.

Что такое TTL

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

Как только мы разберемся с этими вопросами, мы будем углубляться в то, как использовать TTL для выполнения наших собственных требований.

Если мне нужно определить TTL в мире SQL, я бы подумал, что вы добавляете триггер на INSERT или UPDATE, этот триггер делает то, что он берет эту конкретную строку и запускает таймер установленного времени, скажем, 1 час, Через 1 час строка будет удалена сама по себе, если вы не обновите промежуточные записи.

Это наполовину готовый пример, поскольку в нем есть множество нюансов. Как бы то ни было, во многом это верно для индекса TTL MongoDB, вы можете создать предопределенный TTL для любого поля (столбца) с установленным временем и любой записью, вставленной со значением в этом поле. Он удалит запись по истечении установленного времени после значения в этом поле.

Очевидно, что это поле должно быть типа date или timestamp. Итак, предположим, что к полю startAt применен ttl равный 86400 секунд, и мы вставляем запись со значением startAt как 2018–12–27 12: 00: 000, эта конкретная запись будет удалена в 2018 году. –12–28 12: 00: 000. Но подождите, а что, если в промежутке между этим периодом я начну обновление: в 2018–12–28 06: 00: 000, тогда запись будет доступна для удаления в 2018–12–29 06: 00: 000. Мы можем поддерживать запись на неопределенный срок. если мы продолжим обновлять значение как раз вовремя.

Какой возможный сценарий мы будем использовать? Нет предела, один из наиболее очевидных случаев - поддержание сеанса пользователя. установите ttl равным 3600, всякий раз, когда приходит запрос, вы обновляете время с текущим временем и сбрасываете часы, если запрос приходит через 1 час, очевидно, что записи будут недоступны, и вы можете инициировать процесс повторного входа в систему, указывая на то, что сеанс истекший.

Использование БД для поддержания сеанса помогает решить проблему в кластерном сценарии. Вызов может поступать в любой экземпляр, и нам не нужно полагаться на липкие сеансы. профилактика лучше лечения.

Но мы отклоняемся от темы.

Другие примеры

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

Кассандра TTL

Cassandra - одна из самых надежных и широко используемых баз данных без SQL. Это NoSQL на основе столбцов, который отличается от MongoDB, основанного на документах.

И поскольку их базы разные, их TTL разные. Концептуально они делают одно и то же, но по-разному.

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

Поскольку MongoDB основан на документе, TTL изменяет весь документ, вы теряете весь документ (строку, если можете). Хотя TTL определен для одного поля.

Cassandra, с другой стороны, является хранилищем на основе столбцов, поэтому TTL изменяет данные в конкретном столбце. Но подождите, пока дочитаете до конца.

Начнем с примера
- Предположим, у вас запущена cassandra и можно открыть терминал cqlsh.

cqlsh> CREATE KEYSPACE IF NOT EXISTS examples
 WITH REPLICATION = { 
 ‘class’ : ‘SimpleStrategy’, 
 ‘replication_factor’ : 1 };
cqlsh> USE examples;
cqlsh:examples>CREATE TABLE IF NOT EXISTS examples.chat (
id int PRIMARY KEY,
message text,
message_by text,
time timestamp
);
cqlsh:examples> INSERT INTO examples.chat (id, message, message_by, time) VALUES (1,'Hi There','John',toTimestamp(now()));
cqlsh:examples> select * from examples.chat;
id | message  | message_by | time
----+----------+------------+---------------------------------
  1 | Hi There |       John | 2018-12-27 10:00:52.197000+0000
(1 rows)

До сих пор все должно быть понятно, поскольку мы не использовали TTL, поэтому давайте создадим строку, используя TTL.

cqlsh:examples> INSERT INTO examples.chat (id, message, message_by, time) VALUES (2,'Hello','Mary',toTimestamp(now())) USING TTL 30;
cqlsh:examples> select * from examples.chat;
id | message  | message_by | time
----+----------+------------+---------------------------------
  1 | Hi There |       John | 2018-12-27 10:09:43.972000+0000
  2 |    Hello |       Mary | 2018-12-27 10:10:57.275000+0000
(2 rows)

Мы создали новую строку с TTL 30 (в секундах). Следовательно, конкретная строка с идентификатором 2 будет удалена. Ниже запрос через 30 секунд

cqlsh:examples> select * from examples.chat;
id | message  | message_by | time
----+----------+------------+---------------------------------
  1 | Hi There |       John | 2018-12-27 10:09:43.972000+0000
(1 rows)

Первая строка существует, поскольку на ней не было TTL. Похоже, что срок действия строки истекает после прохождения TTL. Но подождите, пока дочитаете до конца.

Теперь мы повторно вставим удаленную строку, используя TTL 60, и на этот раз мы попытаемся выяснить, сколько времени осталось до удаления строки.

cqlsh:examples> INSERT INTO examples.chat (id, message, message_by, time) VALUES (2,'Hello','Mary',toTimestamp(now())) USING TTL 60;
cqlsh:examples> select id,message,message_by,time,ttl(message) from examples.chat;
id | message  | message_by | time                            | ttl(message)
----+----------+------------+---------------------------------+--------------
  1 | Hi There |       John | 2018-12-27 10:09:43.972000+0000 |         null
  2 |    Hello |       Mary | 2018-12-27 10:19:23.953000+0000 |           53
(2 rows)
cqlsh:examples> select id,message,message_by,time,ttl(message) as ttl from examples.chat;
id | message  | message_by | time                            | ttl
----+----------+------------+---------------------------------+------
  1 | Hi There |       John | 2018-12-27 10:09:43.972000+0000 | null
  2 |    Hello |       Mary | 2018-12-27 10:19:23.953000+0000 |   51
(2 rows)
cqlsh:examples> select id,message,message_by,time,ttl(message) as ttl from examples.chat;
id | message  | message_by | time                            | ttl
----+----------+------------+---------------------------------+------
  1 | Hi There |       John | 2018-12-27 10:09:43.972000+0000 | null
  2 |    Hello |       Mary | 2018-12-27 10:19:23.953000+0000 |   35
(2 rows)

Из приведенного выше примера видно, что мы можем вызвать ttl для определенного столбца, в приведенном выше случае я вызываю столбец «сообщение». Он сообщает, сколько времени осталось, когда ttl удалит данные.

Но будет ли ttl (message) отличаться от ttl (message_by) и будут ли они разными для ttl (time)?

Да, они могут быть, но в приведенном выше примере все они будут одинаковыми. Давайте исследуем это дальше.

cqlsh:examples> INSERT INTO examples.chat (id, message, message_by, time) VALUES (2,'Hello','Mary',toTimestamp(now())) USING TTL 300;
cqlsh:examples> select id,message_by,ttl(message) as m_ttl, ttl(message_by) as mb_ttl, ttl(time) as t_ttl from examples.chat;
id | message_by | m_ttl | mb_ttl | t_ttl
----+------------+-------+--------+-------
  1 |       John |  null |   null |  null
  2 |       Mary |   297 |    297 |   297
(2 rows)
cqlsh:examples> select id,message_by,ttl(message) as m_ttl, ttl(message_by) as mb_ttl, ttl(time) as t_ttl from examples.chat;
id | message_by | m_ttl | mb_ttl | t_ttl
----+------------+-------+--------+-------
  1 |       John |  null |   null |  null
  2 |       Mary |   291 |    291 |   291
(2 rows)

Теперь попробуем обновить один столбец с другим значением TTL и посмотрим.

cqlsh:examples> UPDATE examples.chat USING TTL 60 SET message_by='Mary S' WHERE id=2;
cqlsh:examples> select id,message_by,ttl(message) as m_ttl, ttl(message_by) as mb_ttl, ttl(time) as t_ttl from examples.chat;
id | message_by | m_ttl | mb_ttl | t_ttl
----+------------+-------+--------+-------
  1 |       John |  null |   null |  null
  2 |     Mary S |   153 |     57 |   153
(2 rows)
cqlsh:examples> select id,message_by,ttl(message) as m_ttl, ttl(message_by) as mb_ttl, ttl(time) as t_ttl from examples.chat;
id | message_by | m_ttl | mb_ttl | t_ttl
----+------------+-------+--------+-------
  1 |       John |  null |   null |  null
  2 |     Mary S |   137 |     41 |   137
(2 rows)

Итак, у нас разные TTL для разных столбцов. Итак, что произойдет, когда срок действия message_by ttl истечет, а у других нет?

cqlsh:examples> select id,message_by,ttl(message) as m_ttl, ttl(message_by) as mb_ttl, ttl(time) as t_ttl from examples.chat;
id | message_by | m_ttl | mb_ttl | t_ttl
----+------------+-------+--------+-------
  1 |       John |  null |   null |  null
  2 |       null |    18 |   null |    18
(2 rows)

Он удалил данные для этого конкретного столбца, давайте посмотрим, что произойдет, если истечет остаток ttl.

cqlsh:examples> select id,message_by,ttl(message) as m_ttl, ttl(message_by) as mb_ttl, ttl(time) as t_ttl from examples.chat;
id | message_by | m_ttl | mb_ttl | t_ttl
----+------------+-------+--------+-------
  1 |       John |  null |   null |  null
(1 rows)

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

Таким образом, всякий раз, когда ttl истекает, он проверяет значения всех других (неосновных) столбцов. Если все они равны нулю, запись удаляется автоматически.

Но мы еще не закончили. Давай попробуем что-нибудь еще. Вставьте запись с ttl в ограниченное количество столбцов, а затем обновите другой столбец без TTL.

cqlsh:examples> INSERT INTO examples.chat (id, message_by, time) VALUES (2,'Mary',toTimestamp(now())) USING TTL 60;
cqlsh:examples> select id,message,message_by,ttl(message) as m_ttl, ttl(message_by) as mb_ttl, ttl(time) as t_ttl from examples.chat;
id | message  | message_by | m_ttl | mb_ttl | t_ttl
----+----------+------------+-------+--------+-------
  1 | Hi There |       John |  null |   null |  null
  2 |     null |       Mary |  null |     32 |    32
(2 rows)
cqlsh:examples> UPDATE examples.chat SET message='Hello' WHERE id=2;
cqlsh:examples> select id,message,message_by,ttl(message) as m_ttl, ttl(message_by) as mb_ttl, ttl(time) as t_ttl from examples.chat;
id | message  | message_by | m_ttl | mb_ttl | t_ttl
----+----------+------------+-------+--------+-------
  1 | Hi There |       John |  null |   null |  null
  2 |    Hello |       Mary |  null |      7 |     7
(2 rows)
cqlsh:examples> select id,message,message_by,ttl(message) as m_ttl, ttl(message_by) as mb_ttl, ttl(time) as t_ttl from examples.chat;
id | message  | message_by | m_ttl | mb_ttl | t_ttl
----+----------+------------+-------+--------+-------
  1 | Hi There |       John |  null |   null |  null
  2 |    Hello |       null |  null |   null |  null

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

Что, если позже мы обнуляем эту колонну мятежников?

cqlsh:examples> select id,message,message_by,ttl(message) as m_ttl, ttl(message_by) as mb_ttl, ttl(time) as t_ttl from examples.chat;
id | message  | message_by | m_ttl | mb_ttl | t_ttl
----+----------+------------+-------+--------+-------
  1 | Hi There |       John |  null |   null |  null
  2 |    Hello |       null |  null |   null |  null
(2 rows)
cqlsh:examples> UPDATE examples.chat SET message=null WHERE id=2;
cqlsh:examples> select id,message,message_by,ttl(message) as m_ttl, ttl(message_by) as mb_ttl, ttl(time) as t_ttl from examples.chat;
id | message  | message_by | m_ttl | mb_ttl | t_ttl
----+----------+------------+-------+--------+-------
  1 | Hi There |       John |  null |   null |  null

Ну, хорошо, даже если TTL истек, если значение будет установлено на null позже, он все равно удалит запись. Честно говоря, я не ожидал такого поведения. поэтому, даже если срок действия ttl истек, он проверяет все правила нулевого столбца на более поздних событиях.

Напротив, давайте попробуем обновить значение до нуля для всех столбцов до первой строки с идентификатором 1, у которой никогда не было TTL.

cqlsh:examples> select id,message,message_by,ttl(message) as m_ttl, ttl(message_by) as mb_ttl, ttl(time) as t_ttl from examples.chat;
id | message  | message_by | m_ttl | mb_ttl | t_ttl
----+----------+------------+-------+--------+-------
  1 | Hi There |       John |  null |   null |  null
(1 rows)
cqlsh:examples> UPDATE examples.chat SET message=null,message_by=null,time=null WHERE id=1;
cqlsh:examples> select id,message,message_by,ttl(message) as m_ttl, ttl(message_by) as mb_ttl, ttl(time) as t_ttl from examples.chat;
id | message | message_by | m_ttl | mb_ttl | t_ttl
----+---------+------------+-------+--------+-------
  1 |    null |       null |  null |   null |  null
(1 rows)
cqlsh:examples> select * from examples.chat;
id | message | message_by | time
----+---------+------------+------
  1 |    null |       null | null

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

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

cqlsh:examples> INSERT INTO examples.chat (id, message, message_by, time) VALUES (2,'Hello','Mary',toTimestamp(now())) USING TTL 60;
cqlsh:examples> select id,message,message_by,ttl(message) as m_ttl, ttl(message_by) as mb_ttl, ttl(time) as t_ttl from examples.chat;
id | message  | message_by | m_ttl | mb_ttl | t_ttl
----+----------+------------+-------+--------+-------
  1 | Hi There |       John |  null |   null |  null
  2 |    Hello |       Mary |    58 |     58 |    58
(2 rows)
cqlsh:examples> INSERT INTO examples.chat (id,message,time) VALUES (2,'Hola',toTimestamp(now()));
cqlsh:examples> select id,message,message_by,ttl(message) as m_ttl, ttl(message_by) as mb_ttl, ttl(time) as t_ttl from examples.chat;
id | message  | message_by | m_ttl | mb_ttl | t_ttl
----+----------+------------+-------+--------+-------
  1 | Hi There |       John |  null |   null |  null
  2 |     Hola |       Mary |  null |     35 |  null

Пришло время подвести итоги замеченным нами моментам и еще кое-что.

Резюме

  • TTL используется для устаревших записей или данных.
  • Cassandra TTL применяется на уровне столбца.
  • Если запись вставляется с TTL, отдельный TTL будет применяться ко всем столбцам, упомянутым в операторе вставки.
  • Всякий раз, когда TTL истекает в Cassandra для столбца, он проверяет все значения непервичного столбца в записи, если все значения равны нулю, запись удаляется.
  • Даже после того, как TTL истек в Cassandra, и в более поздний момент все непервичные значения столбца станут нулевыми, запись будет удалена.
  • TTL не применяется к основным столбцам в Cassandra.
  • Когда столбцы с текущим TTL обновляются без значений TTL, существующий TTL удаляется из этих столбцов. Другими словами, нельзя обновить значение столбца с TTL, не изменив TTL, ни с помощью нового TTL, ни путем его удаления.
  • TTL не применяется для столбцов типа Cassandra counter.

В заключение я хотел бы сказать, что в Cassandra TTL следует использовать с осторожностью, иначе это может привести к нестабильному поведению. В том виде, как предоставляются общие примеры, похоже, что в Cassandra TTL применяется на уровне строки, хотя в нем четко упоминается, что на самом деле это уровень столбца.

По сравнению с MongoDB, у которых есть предопределенное значение TTL на уровне коллекции, Cassandra обеспечивает большую детализацию с TTL, поскольку разные записи и столбцы могут иметь разный TTL. Однако одно ключевое отличие заключается в том, что Mongo сравнивает TTL со значениями полей, тогда как Cassandra вычисляет TTL по времени вставки или обновления.

Вышеупомянутые примеры были запущены в Cassandra версии 3.11