nsq icon indicating copy to clipboard operation
nsq copied to clipboard

nsqd: discover topic/channel paused state on new topic discovery

Open maplessssy opened this issue 4 years ago • 23 comments

Fix #1199

maplessssy avatar Aug 08 '20 09:08 maplessssy

@jehiah @mreiferson @ploxiln This PR is ready for review. PTAL.

maplessssy avatar Aug 08 '20 14:08 maplessssy

Here is the design:

  1. Supports send topic/channel paused state through command[register], see go-nsq pr.
  2. Nsqd send states to nsqlookupd when topic/channel create,delete and paused,unpaused.
  3. Nsqlookupd store these states, and nsqd can discover topic/channel paused state on new topic discovery through the HTTP API that nsqlookupd provides.

see more details in the code. : )

maplessssy avatar Aug 08 '20 14:08 maplessssy

Thanks for taking a first pass at this @thekingofworld! 🙏

mreiferson avatar Aug 08 '20 20:08 mreiferson

@jehiah @mreiferson @ploxiln This PR is ready for review. PTAL.

maplessssy avatar Aug 09 '20 13:08 maplessssy

@mreiferson This PR is ready for review. PTAL. /cc @ploxiln @jehiah

maplessssy avatar Aug 10 '20 15:08 maplessssy

/cc @mreiferson @ploxiln @jehiah any of you can help to take a look at this?🙏

maplessssy avatar Aug 12 '20 11:08 maplessssy

@mreiferson Ping.

maplessssy avatar Aug 14 '20 12:08 maplessssy

/cc @mreiferson Thank you for suggestions above, it's great. I have finished all, the code seems to more clearly, please take another look. Thanks again for your patience.

maplessssy avatar Aug 15 '20 13:08 maplessssy

Continuing to improve! Thanks for your patience 🙏

My big high-level concern now is that these new paths in nsqlookupd are going to be significantly more expensive. In the /channels case, we're doing multiple passes over data in RegistrationDB to filter and lookup paused state in producers. Considering #1208, we should think about better data structures to use to store this data to make these newer, more complex queries performant.

cc @andyxning

Agree.

In the /channels case, we're doing multiple passes over data in RegistrationDB to filter and lookup paused state in producers.

After this, seems like handle the "*" case for FindRegistrations is not enough. I have to think about how to solve this whole problem. @mreiferson @andyxning Any ideas?

like we can add two additional maps to handle "*" case for FindRegistrations, we can also add additional map handle the state lookup for topic/channel, doesn't it?

maplessssy avatar Aug 17 '20 14:08 maplessssy

@mreiferson I added some benchmarks for the /channels case, the execution results are as follows:

image

It seems still fast enough, I doubt if the situation of write lock starvation really exists?

maplessssy avatar Aug 29 '20 08:08 maplessssy

@mreiferson Ping.

maplessssy avatar Aug 31 '20 11:08 maplessssy

@mreiferson @jehiah @ploxiln Anyone can help to take a look at this? It has waited for more than 10 days...

maplessssy avatar Sep 10 '20 12:09 maplessssy

Hi folks, let's keep going.[Doge] if there are any problems, please let me know and I will try my best to solve them. Let us make nsq more powerful. /cc @mreiferson @jehiah @ploxiln

maplessssy avatar Sep 13 '20 11:09 maplessssy

hi @thekingofworld, sorry for the delay, I'll try to find some time this week to take a closer look. We do know that at larger scale there are performance issues that exist (https://github.com/nsqio/nsq/pull/1208), and this PR will make some queries perform worse.

mreiferson avatar Sep 13 '20 19:09 mreiferson

Well, I read the related discussion about the PR #1208. I'm wondering if there is more detailed data that indicate how slow these queries are, such as how long does a query take, and how many topics, how many channels, how many producers... After recurring this slow situation, we can verify how much efficiency the new optimization scheme can improve. /cc @mreiferson

maplessssy avatar Sep 14 '20 13:09 maplessssy

@mreiferson I added some benchmarks for the /channels case, the execution results are as follows:

image

It seems still fast enough, I doubt if the situation of write lock starvation really exists?

By the way, benchmarks show that these queries are still fast.

maplessssy avatar Sep 14 '20 13:09 maplessssy

I think that the situation that #1208 is attempting to optimize, which the existing benchmark setups here do not emulate, is when there are many channels per topic, and they are constantly being added and removed (as ephemeral channels tend to do when consumers connect and disconnect). Each add and remove does a "write" lock/unlock of the RWMutex, and this blocks all the "read" locks of the lookups. The current benchmarks setup just two channels per topic, and do lookups without concurrent updates, and only time the lookups part.

ploxiln avatar Sep 14 '20 14:09 ploxiln

@ploxiln yeah, the situation you described is right. But I think the key is how FindRegistrations will behave in * case when db is very large. So I added some benchmarks for this, the results are shown below: image When topic=64, channel=512, producer=512, each operation takes 11ms. When topic=512, channel=512, producer=512, Memory exceeds 10G, I think this is beyond normal. It seems like we can add additional maps to improve performance for * case. /cc @ploxiln @mreiferson

maplessssy avatar Sep 15 '20 16:09 maplessssy

@mreiferson @ploxiln Let's continue to this. Our previous discussion stopped at the performance of the case of /channels. Recently I added an additional map to improve the performance of the query, which is essentially optimizing the function FindRegistrations, which is called with * . PTAL.

Comparison before and after optimization:

Performance increased by 40%.

image

image

Corns:

  • This will add some pressure on the memory since a new memory will be allocated.

maplessssy avatar Dec 05 '20 13:12 maplessssy

@mreiferson @ploxiln Ping.

maplessssy avatar Dec 23 '20 02:12 maplessssy

Thanks for continuing to push this forward @thekingofworld.

The approach here will now be much more costly on the write (registration) side, because each write will now have to walk the whole structure and produce the cached "high performance" map.

Instead, we should concurrently update both the standard and new "high performance" maps during each mutation.

The discussion in https://github.com/nsqio/nsq/pull/1208#issuecomment-549509152 (from "if sync.Map everywhere is too much overhead" down) and https://github.com/nsqio/nsq/pull/1208#issuecomment-643821646 has the most relevant context for what needs to happen here.

mreiferson avatar Dec 29 '20 00:12 mreiferson

Instead, we should concurrently update both the standard and new "high performance" maps during each mutation.

agree, update highspeed map during each mutation instead walk the whole structure and produce the cached "high performance" map.

@mreiferson done, PTAL.

maplessssy avatar Jan 01 '21 03:01 maplessssy

@mreiferson ping. let's finish it...

maplessssy avatar Feb 09 '21 02:02 maplessssy