In the process of enhancing MySQL replication with new features for our users, we also improve the internals. A lot of work goes also to modernize the codebase and make it easier to maintain and obviously extend as well.
In MySQL 8.0.18, we have extended the set of internal services with a group replication message passing service, therefore generalizing the communication framework for group replication. It allows other components than just the group replication plugin to engage the group communication layer.
So, how is the design ?
MySQL services allow the plugins to access functionality of server, this is the base of Group Replication delivery message service, please consult here to get more details about service design.
The Group Replication delivery message service is composed of two services:
- to send messages using Group Replication communication mechanism
- to receive and deliver to components that are subscribed to that message type
The messages types are identified by a tag mechanism, a string that shall not have the reserved prefix mysql_.
The service is agnostic of type and content of payload being transmitted , so encoding/decoding responsibility belongs to its sender/receiver.
When no receiver is registered there is no error from the service but in case of a receiver return error the member will leave the group, as Group Replication cannot guarantee consistency when one member failed to process the message.
If the module using Group Replication delivery message service needs to communicate to all members of the group it needs to confirm all of them support it. If server has a previous version it will discard the unknown messages and won’t have send service available.
And an example
For testing purposes we added extra functionality to replications_observer_example plugin, it validates the behavior of group replication message service and that can be used as reference for developing
your own.
It was implemented a simple usage example were a server send a message and all members that receive the message will log it on error log.
To send messages you have to acquire the send service and write the message, a snippet of the code:
1
2
3
4
5
6
7
8
9
10
11
|
SERVICE_TYPE(registry) *plugin_registry = mysql_plugin_registry_acquire(); my_service svc( "group_replication_message_service_send", plugin_registry); my_service svc_error("mysql_runtime_error", plugin_registry); if (svc.is_valid()) { const size_t payload_length = static_cast(args->lengths[1]); const bool error = svc->send( "IRC", reinterpret_cast(args->args[1]), payload_length); … |
All members ONLINE on the group, even the member that sent the message, will
receive the message. Then, group replication will see the modules that are
subscribed and notify that there is a new message.
Using pseudo code, we need to define a function which will be called by service when a message is received:
1
2
3
|
BEGIN_SERVICE_IMPLEMENTATION(replication_observers_example, group_replication_message_service_recv) recv, END_SERVICE_IMPLEMENTATION(); |
To print messages with tag “IRC” to error log we can:
1
2
3
4
5
6
7
8
|
DEFINE_BOOL_METHOD(IRC::recv, (const char *tag, const size_t, const unsigned char *data, size_t)) { DBUG_TRACE; if (strcmp(tag, "IRC") == 0) { LogPluginErr(ERROR_LEVEL, ER_LOG_PRINTF_MSG, reinterpret_cast<const char *>(data), data_length); } return false; } |
This is a small part of the code we advice to explore gr_message_service_example.cc to look the full code.
Use it
If you are interested further into this topic or even developing your own extensions to MySQL, you may find more information in the doxygen documentation here. Then play with the code itself, by downloading it from the usual place. Have fun!