2014-11-06 2 views
2

Я хотел бы сделать базовые часы с помощью StackExchange.Redis. Если в ходе транзакции изменяется ключ, он терпит неудачу.Как сделать основной чат с помощью StackExchange.Redis

StackExchange.Redis очень хорошо отнесся к «Условие» api, которое поддерживает концепции «Равно» и «Существует».

Это действительно хорошо, но я хотел бы просто сделать что-то вроде «Без изменений». Я мог бы что-то упустить, но для меня сейчас не очевидно, как это сделать.

Можно ли сделать что-то вроде:

var transaction = redis.CreateTransaction(); 
transaction.AddCondition(Condition.StringUnchanged("key")); //the API here could maybe be simplified 
var val = transaction.StringGet("key"); //notably, this is not async because you would have to get the result immediately - it would only work on watched keys 
transaction.StringSetAsync("key", val + 1); 
transaction.Execute(); 

или даже возможно лучший вариант (который будет делать то же самое):

var transaction = redis.CreateTransaction(); 
var val = transaction.Watch("key"); //this would return the value! 
transaction.StringSetAsync("key", val + 1); 
transaction.Execute(); 

В настоящее время единственным способом я понимаю делать это было бы сделать что-то в соответствии с:

Какой из попыток чтения код SE.Redis Я понимаю, перевести что-то вроде (не уверен, насколько точны это):

val = GET key 
WATCH key 
MULTI 
val = val + 1 
SET key $val 
checkVal = GET key 
(then if checkVal != val:) UNWATCH 
(otherwise:) EXEC 

Я все еще учусь больше о Redis, но я не совсем уверен, что польза от этого , Бы не вы, а конечный результат будет что-то больше, как это ?:

WATCH key 
MULTI 
val = GET key 
val = val + 1 
SET key $val 
EXEC 

Или это не возможно с тем, как SE.Redis работает?

+0

Я отредактирую свой ответ, чтобы отразить ваше редактирование –

ответ

0

Причина, по которой WATCH не раскрывается напрямую, связана с тем, как SE.Redis предназначен для мультиплексирования команд из разных стеков вызовов в одном соединении. Это делает необходимым, чтобы любая транзакционная работа была очень плотно управляемой.

Я не совсем понимаю, что цель «неизменной» была бы сама по себе, без сравнения с каким-то известным значением - иначе вы просто создаете условие гонки. Конечно, можно было бы добавить поддержку для этого, но я бы очень хотел сначала понять ожидаемый прецедент. Вы можете объяснить?


Re your edit; ваш предпочтительный пример (последний) просто невозможно с redis - ничего общего с SE.Redis; если вы делаете GET внутри MULTI, вы не получите ответ до завершения EXEC - так что вы не можете использовать значение в SET: он еще не доступен.

Если бы не мультиплексирование, вы можете изменить порядок свой второй пример (основанный на том, что делает SE.Redis) немного:

WATCH key 
val = GET key 
MULTI 
val = val + 1 
SET key $val 
EXEC 

это использование WATCHтипичный: вы смотреть то, что вы запрашиваете заранее, то вы знаете, что {key} не изменился во время этого цикла (или, по крайней мере, транзакция будет прервана, не противоречивое состояние).Тем не менее, не очень хорошо работает с мультиплексором, поэтому SE.Redis заставляет вас выбрать маршрут для получения значения перед транзакцией, а затем позволяет сравнить значение, чтобы утверждать, что оно не изменилось. Тот же результат; немного другой подход, но он мультиплексор-безопасен. Подробнее об этой теме see here.

+0

Спасибо за ответ, я обновил вопрос, чтобы, надеюсь, объяснить его лучше. –

+0

Хорошо, очень полезно. Два ключа, которых я отсутствовал, были 1: вы должны получить значение 'WATCH'ed перед' MULTI', или оно не работает. 2: из-за мультиплексора концепция «неизменной» на самом деле не работает - вам нужно что-то сравнить. Хорошо знать. –

+0

На другой ноте - SE.Redis - это потрясающая библиотека, с которой вы можете работать, благодаря всей вашей работе над ней. –