New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implements Mirror Queue Sync in Batches #344
Conversation
To test mirror sync you can use these commands:
|
false = dict:is_key(MsgId, SS), %% ASSERTION | ||
Sizes + rabbit_basic:msg_size(Msg)} | ||
end, {[], false, 0}, Publishes), | ||
Publishes2 = lists:reverse(Publishes1), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we reverse the list after foldl
, how about using foldr
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mostly from the docs
foldl/3 is tail recursive and would usually be preferred to foldr/3.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Aslo AFAIK list reverse is a BIF
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm fine to change this to foldr if you think it's required
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lets keep foldl
.
[policy_validator, <<"ha-promote-on-shutdown">>, ?MODULE]}}, | ||
{requires, rabbit_registry}, | ||
{enables, recovery}]}). | ||
|
||
%% For compatibility with versions that don't support sync batching. | ||
-define(DEFAULT_BATCH_SIZE, 1). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are we talking about pre-3.6.0 versions here? Mixed 3.6.0/3.5.x clusters are not allowed, so we can use a different default.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right. I think this constant came to life on my first POCs, but is not required anymore. Probably not used in the code.
On Oct 10, 2015, at 3:28 PM, Michael Klishin notifications@github.com wrote:
In src/rabbit_mirror_queue_misc.erl:
[policy_validator, <<"ha-promote-on-shutdown">>, ?MODULE]}}, {requires, rabbit_registry}, {enables, recovery}]}).
+%% For compatibility with versions that don't support sync batching.
+-define(DEFAULT_BATCH_SIZE, 1).
Are we talking about pre-3.6.0 versions here? Mixed 3.6.0/3.5.x clusters are not allowed, so we can use a different default.—
Reply to this email directly or view it on GitHub.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is used via rabbit_mirror_queue_misc:sync_batch_size/0
. I just don't think it serves any compatibility purpose and therefore has to be 1. I'd suggest making it 16K or so and moving to the app config.
Thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changing the default to 16K leads to sync test failures.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking at the code I remembered the original purpose. The idea is for it to be 1, so you either use non-batch sync, or batched sync in case the policy has been set. The logic that assumes policy batch size either 1
or > 1
is here: https://github.com/rabbitmq/rabbitmq-server/blob/rabbitmq-server-336/src/rabbit_mirror_queue_sync.erl#L212
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, that makes more sense. I had changes that moved the default to the app file, bumped the default and simplified sync_batch_size/0
, the error is
Running 5 of 72 tests; FILTER=eager_sync; COVER=false
eager_sync
----------
eager_sync: [setup] [running]rabbit_test_runner: make_test_multi...*failed*
in function sync_detection:wait_for_sync_status/5 (test/src/sync_detection.erl, line 159)
in call from eager_sync:sync/2 (test/src/eager_sync.erl, line 167)
in call from eager_sync:eager_sync/1 (test/src/eager_sync.erl, line 63)
in call from rabbit_test_runner:'-make_test_multi/7-fun-2-'/3 (src/rabbit_test_runner.erl, line 129)
**error:{sync_status_max_tries_failed,[{queue,<<"ha.two.test">>},
{node,c@urano},
{expected_status,true},
{max_tried,100.0}]}
output:<<"">>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see no reason to not batch all the time, only making batch size configurable (with 16K or so by default).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The problem is finding the right batch size. 16k for big messages is too much. It can even cause a network partition (reason why we have max msg size 2Gb in the first place). Finding the right value depends on workload (this is explained on the related rabbitmq-website PR), but if we provide a default, I think it has to be lower.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Messages that are hundreds of MB in size are probably very rare. Most messages on common workloads are < 4K in size.
We can go with 4096 as default value and those with large messages can adjust it. 4K * 4 KiB per message = 16 MiB of payload, not particularly excessive.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@carlhoerberg can you please help us pick the default batch size for eager (full) mirror sync? Maybe you have some stats on median/95th percentile message size distribution at cloudamqp, or any other data that can help us here?
@michaelklishin ready for another round. bugs discovered/fixed were:
|
Implements Mirror Queue Sync in Batches
This PR is related to these other PRs, so they have to be merged together:
rabbitmq/rabbitmq-test#4
rabbitmq/rabbitmq-website#87
In order to improve the performance of mirror queue sync, this PR introduces the concept of batch publishing for the backing queue.
There are 2 new callbacks:
batch_publish/4
and 'batch_publish_delivered/4`. Both behave like their non batch counterparts, but in this case they accept batches of messages, which can use optimization like the ones already in place for queue purge, paging, and so on.These new callbacks have been implemented for
rabbit_variable_queue
,rabbit_priority_queue
,rabbit_mirror_queue_master
andrabbit_mirror_queue_slave
.Apart from this, sync'ing mirrored queues can now be done in batches of messages, instead of one by one. With a batch size of 20k msgs, 1 million messages can be sync'ed in 6 seconds (it was 60 seconds before).
To configure mirror sync'ing, there's a new mirroring policy called
ha-sync-batch-size
, which is documented here: rabbitmq/rabbitmq-website#87The sync'ing tests from rabbitmq-test have been updated to also test for
ha-sync-batch-size
and the non-batch mode.Fixes #336