Как реализовать конвейерные запросы Redis с помощью Booksleeve? - PullRequest
6 голосов
/ 05 декабря 2011

Я немного запутался в разнице между транзакцией Redis и конвейером и, в конечном счете, в том, как использовать конвейеры с Booksleeve.Я вижу, что Книжный рукав поддерживает функцию транзакции Redis (MULTI / EXEC), но в его API / тестах нет упоминания о функции конвейерной обработки.Однако в других реализациях ясно, что существует различие между конвейерами и транзакциями, а именно в atomicity , о чем свидетельствует приведенная ниже версия redis-ruby, но в некоторых местах термины кажутсядля взаимозаменяемости.

реализация redis-ruby:

r.pipelined {
  # these commands will be pipelined
  r.get("insensitive_key")
}

r.multi {
  # these commands will be executed atomically
  r.set("sensitive_key")
}

Я бы просто использовал MULTI / EXEC вместо этого, но они, кажется, блокируют вседругие пользователи, пока транзакция не была завершена (не обязательно в моем случае), поэтому я беспокоюсь об их производительности.Кто-нибудь использовал конвейеры с Booksleeve или есть идеи по их реализации?

Ответы [ 3 ]

6 голосов
/ 11 октября 2012

В BookSleeve, все всегда передается по конвейеру. Там нет синхронных операций. Ни одного. Таким образом, каждая операция возвращает некоторую форму Task (может быть ваниль Task, может быть Task<string>, Task<long> и т. Д.), Которая в какой-то момент в будущем (т.е. когда Redis отвечает) будет иметь значение. Вы можете использовать Wait в своем коде вызова для выполнения синхронного ожидания или ContinueWith / await (функция языка C # 5) для выполнения асинхронного обратного вызова.

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

Итак: причина, по которой нет явного .pipelined, заключается в том, что все является конвейерным и асинхронным.

4 голосов
/ 07 декабря 2011

Pipelining - это коммуникационная стратегия на уровне протокола, которая не имеет ничего общего с атомарностью.Оно полностью ортогонально понятию «транзакции».(Например, вы можете использовать MULTI .. EXEC в конвейерном соединении.)

Что такое конвейер?

Самым основным соединителем для redis будет синхронный клиент, взаимодействующий в режиме запрос-ответ,Клиент отправляет запрос, а затем ждет ответа от Redis перед отправкой следующего запроса.

При конвейерной обработке клиент может продолжать отправлять запросы, не останавливаясь, чтобы увидеть ответ Redis на каждый запрос.Redis, конечно, является однопоточным сервером и естественной точкой сериализации, и, таким образом, порядок запросов сохраняется и отражается в порядке ответов.Это означает, что клиент может иметь один поток, отправляющий запросы (обычно путем удаления из очереди запросов), а другой поток постоянно обрабатывает ответы от Redis.Обратите внимание, что, конечно, вы все равно можете использовать конвейерную обработку с однопоточным клиентом, но вы теряете некоторые преимущества.Двухпоточная модель позволяет полностью использовать ваш локальный процессор и пропускную способность сети (например, насыщение).

Если вы следите за этим до сих пор, вы должны спросить себя: хорошо, как запрос и ответы совпадают на стороне клиента?Хороший вопрос!Есть разные способы подойти к этому.В JRedis я обертываю запросы в объект (java) Future, чтобы справиться с асинхронностью обработки запроса / ответа.Каждый раз, когда отправляется запрос, соответствующий объект Future оборачивается ожидающим объектом ответа и ставится в очередь.Прослушиватель ответов просто извлекает из этого элемента очереди 1 за раз, анализирует ответ (поток) и обновляет будущий объект.

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

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

Если интерфейс с конвейером является асинхронным, то даже однопоточное клиентское приложение может выиграть.Пропускная способность увеличивается по крайней мере на порядок.

(Предостережения с конвейерной обработкой: написать отказоустойчивый конвейерный клиент нетривиально.)

В идеале я должен использовать диаграмму, нообратите внимание на то, что происходит в конце клипа: http://www.youtube.com/watch?v=NeK5ZjtpO-M

1 голос
/ 07 декабря 2011

Вот ссылка на Документация по транзакциям Redis

Относительно BookSleeve, пожалуйста, обратитесь к этому сообщению от Marc.

"CreateTransaction () создает промежуточную область для построения команд (используя точно такой же API) и получения будущих результатов. Затем, когда вызывается Execute (), буферизованные команды собираются в модуль MULTI / EXEC и отправляются в непрерывный блок (мультиплексор, очевидно, отправит все это вместе). "

Если вы создаете свои команды внутри транзакции, они автоматически будут "конвейерными".

...