Новичок здесь (и кажется, что это может быть вопрос новичков). Использование Ubuntu 14.04
со свежей установкой Cassandra 2.1.1, CQL 3.2.0
(говорится). Запись базы данных для сайта CherryPy, изначально в качестве базы данных сеансов.Cassandra CQL UPDATE с IF
Я придумал схему для своего рода «блокировка строк» в качестве блокировки сеанса, но, похоже, она не висит вместе, поэтому я уменьшил ее до простой тестовой программы против местного Cassandra экземпляр. Чтобы запустить этот тест, я открываю два окна терминала, чтобы одновременно запускать два экземпляра python, каждый с разными номерами экземпляров («1» и «2»).
import time, sys, os, cassandra
from cassandra.cluster import Cluster
from cassandra.auth import PlainTextAuthProvider
instance = sys.argv[1]
cluster = Cluster(auth_provider=PlainTextAuthProvider(username='cassandra', password='cassandra'))
cdb = cluster.connect()
cdb.execute("CREATE KEYSPACE IF NOT EXISTS test WITH replication = {'class':'SimpleStrategy', 'replication_factor' : 1}")
cdb.execute("CREATE TABLE IF NOT EXISTS test.test (id text primary key, val int, lock text)")
cdb.execute("INSERT INTO test.test (id, val, lock) VALUES ('session_id1', 0, '') ")
raw_input('<Enter> to start ... ')
i = 0
while i < 10000:
i += 1
# set lock
while True:
r = cdb.execute("UPDATE test.test SET lock = '%s' WHERE id = 'session_id1' IF lock = '' " % instance)
if r[0].applied == True:
break
# check lock and increment val
s0 = cdb.execute("SELECT val,lock FROM test.test WHERE id = 'session_id1' ")[0]
if s0.lock != instance:
print 'error: instance [%s] %s %s' % (instance, s0, r[0])
cdb.execute("UPDATE test.test SET val = %s WHERE id = 'session_id1'", (s0.val + 1,))
# clear lock
cdb.execute("UPDATE test.test SET lock = '' WHERE id = 'session_id1' ")
time.sleep(.01)
Так что, если я правильно понимаю, UPDATE..IF должен быть «прикладной» (и разрыв принято), только если текущее значение блокировки является «» (пустая строка), так что это должен дать эффективная эксклюзивная блокировка строки.
Проблема заключается в том, что тест 's1.lock != instance'
довольно часто срабатывает, показывая, что, несмотря на UPDATE применяется значение замка впоследствии по-разному до сих пор «» или что в другом случае ...
Я знаю, что когда Я перехожу к кластеру, мне придется решать проблемы согласованности, но это противоречит единому локальному экземпляру Cass. Конечно, последовательность не должна быть проблемой здесь?
Я не могу представить, что эта форма CQL сломана (tm), так что это должен быть я. Что я делаю неправильно, или что я не понимаю? ТИА.
ОБНОВЛЕНИЕ: Хорошо, я много поработал над этим, прежде чем я разместил здесь, и теперь провел день с тех пор, как он сделал то же самое.
В частности, StackOverflow размещения Cassandra Optimistic Locking решает подобную проблему (по другой причине), и его решение было:
"update table1 set version_num = 5 where name = 'abc' if version_num = 4"
, которые он говорит, работает для него - но на самом деле именно то, что я делаю , но который не работает для меня.
Так что я считаю, что мой подход звучит, но, очевидно, у меня проблема.
Есть ли какие-либо экологические проблемы, которые могут повлиять на меня? (Монтаж, вещий, независимо от ...)
Я знаю, что это очень старое сообщение, и я, к сожалению, не проверил это сам, но простота в том, что с таким механизмом, когда ваше обновление гарантируется атомарностью с определенным синтаксисом - вам нужно сделать это с КАЖДОЙ вы выполняете. Вы не можете сделать «UPDATE .. SET ... IF ...», а затем запустить инструкцию сразу после нее без части «... IF ...», потому что что-то еще может изменить ее с тех пор. Снова я не тестировал, но из того, что я могу сказать, это источник проблем, которые вы описываете. –