Rethinkdb атомарное извлечение и обновление
Скажем, у меня есть следующая структура данных:
{ "name": "i1", "time": 1, "status": 1}
{ "name": "i2", "time": 2, "status": 1}
{ "name": "i3", "time": 3, "status": 1}
{ "name": "i4", "time": 4, "status": 2}
Мне нужно получить элемент с наибольшим временем и "status" = 1. Затем обновите его "status" до 2, все это атомарно, чтобы этот же элемент не мог быть извлечен другим потребителем в одно и то же время.
Это возможно с rethinkdb?
1 ответ
Поскольку атомарность в RethinkDB гарантируется только на уровне документа, это возможно только частично.
Вы можете сделать что-то вроде этого:
r.table(...)
.orderBy(index=r.desc("time"))
.filter({status: 1})
.limit(1)
.update(r.branch(r.row["status"] == 1, {status: 2}, {}), return_changes=True)
Все внутри update
будет применяться атомарно. Таким образом, если другой клиент уже установил статус записи в 2, запрос вернет {неизмененный: 1}, и вы можете запустить его снова, пока он не выполнит обновление.
Однако это не гарантирует, что в то время, когда обновление выполнено, выбранный документ все еще является документом с наибольшим временем. Другой клиент мог вставить новый документ с более длительным временем, пока выполнялся этот запрос, что заставило бы запрос обновить статус единственного тогда второго по величине документа до 2.
Для полной защиты от этого вам необходимо использовать явный мьютекс или блокировку чтения / записи для таблицы.