Redis
 sql >> база данни >  >> NoSQL >> Redis

Как работи PubSub в BookSleeve/ Redis?

1:във вашия пример има само един канал (Test ); каналът е просто името, използвано за конкретен пъб/подборник. Необходимо е обаче да използвате 2 връзки поради спецификата на това как работи redis API. Връзка, която иманякаквата абонаментите не могат да правят нищо друго освен:

  • слушайте съобщения
  • управлява собствените си абонаменти (subscribe , psubscribe , unsubscribe , punsubscribe )

Не разбирам обаче това:

private static Dictionary<string, RedisSubscriberConnection>

Не трябва да имате нужда от повече от една абонатна връзка, освен ако не се грижите за нещо конкретно за вас. Една абонатна връзка може да обработва произволен брой абонаменти. Бърза проверка на client list на един от моите сървъри и имам една връзка с (към момента на писане) 23 002 абонамента. Което вероятно може да бъде намалено, но:работи.

2:абонаментите за шаблони поддържат заместващи знаци; така че вместо да се абонирате за /topic/1 , /topic/2/ и т.н. можете да се абонирате за /topic/* . Името на действителния канал, използван от publish се предоставя на получателя като част от подписа за обратно повикване.

И двете могат да работят. Трябва да се отбележи, че ефективността на publish се влияе от общия брой уникални абонаменти - но честно казано все още е глупаво бърз (като:0ms), дори ако имате десетки хиляди абонирани канали, използвайки subscribe вместо psubscribe .

Но от publish

Времева сложност:O(N+M), където N е броят на клиентите, абонирани за приемащия канал, а M е общият брой абонирани модели (от всеки клиент).

Препоръчвам да прочетете документацията за redis на pub/sub.

Редактиране за последващи въпроси:

а) Предполагам, че ще трябва да „публикувам“ синхронно (използвайки Result или Wait()), ако искам да гарантирам, че редът на изпращане на артикули от същия издател се запазва при получаване на артикули, нали?

това няма да има никаква разлика; тъй като споменавате Result / Wait() , предполагам, че говорите за BookSleeve - в този случай мултиплексорът вече запазва реда на командите. Самият Redis е еднонишков и винаги ще обработва команди в една връзка по ред. Обаче:обратните извиквания на абоната могат да се изпълняват асинхронно и могат да бъдат предадени (отделно) на работна нишка. В момента проучвам дали мога да принудя това да бъде в ред от RedisSubscriberConnection .

Актуализация:от 1.3.22 нататък можете да зададете CompletionMode към PreserveOrder - тогава всички обратни извиквания ще бъдат завършени последователно, а не едновременно.

б) след като направя корекции според вашите предложения, получавам страхотно представяне при публикуване на няколко елемента, независимо от размера на полезния товар. Въпреки това, когато изпращате 100 000 или повече артикула от един и същ издател, ефективността пада бързо (до 7-8 секунди само за изпращане от моята машина).

Първо, това време звучи високо - локално тестване получавам (за 100 000 публикации, включително изчакване на отговора за всички тях) 1766 мс (локално) или 1219 мс (отдалечено) (това може да звучи контраинтуитивно, но моето "локално" е " t изпълнявам същата версия на redis; моето "отдалечено" е 2.6.12 на Centos; моето "локално" е 2.6.8-pre2 на Windows).

Не мога да направя действителния ви сървър по-бърз или да ускоря мрежата, но:в случай че това е фрагментация на пакети, добавих (само за вас) SuspendFlush() / ResumeFlush() двойка. Това деактивира нетърпеливото прочистване (т.е. когато опашката за изпращане е празна; други видове прочистване все още се случват); може да откриете, че това помага:

conn.SuspendFlush();
try {
    // start lots of operations...
} finally {
    conn.ResumeFlush();
}

Имайте предвид, че не трябва да Wait докато не продължите, защото докато не извикате ResumeFlush() може да има някои операции все още в буфера за изпращане. След като всичко това е на място, получавам (за 100 000 операции):

local: 1766ms (eager-flush) vs 1554ms (suspend-flush)
remote: 1219ms (eager-flush) vs 796ms (suspend-flush)

Както можете да видите, това помага повече с отдалечените сървъри, тъй като ще пуска по-малко пакети през мрежата.

Не мога да използвам транзакции, защото по-късно артикулите, които предстои да бъдат публикувани, не са налични наведнъж. Има ли начин да се оптимизира с тези знания в ума?

Мисля който е адресиран от горното - но имайте предвид, че наскоро CreateBatch също беше добавен. Пакетът работи много като транзакция - просто:без транзакцията. Отново, това е друг механизъм за намаляване на фрагментацията на пакети. Във вашия конкретен случай подозирам, че спирането/възобновяването (при флъш) е най-добрият ви залог.

Препоръчвате ли да имате една обща RedisConnection и една RedisSubscriberConnection или друга конфигурация, за да може такава обвивка да изпълнява желаните функции?

Стига да не извършвате операции по блокиране (blpop , brpop , brpoplpush и т.н.), или поставяне на големи BLOB-ове (потенциално забавяне на други операции, докато се изчисти), тогава една връзка от всеки тип обикновено работи доста добре. Но YMMV в зависимост от вашите точни изисквания за използване.




  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Redis, слушане на pubsub събития и превръщането им в поток за по-надеждно потребление

  2. Как да изброя всички Redis бази данни?

  3. Изпълнение на пакети от команди с помощта на redis cli

  4. Деактивирайте прозрачните огромни страници от Kubernetes

  5. Множество ключове, сочещи към една стойност в Redis (кеш) с java