Real-Time ORM Master/Slave Replication via WebSockets
In a previous
article, we presented how Master/Slave replication may be easily
implemented in mORMot's RESTful ORM.
Do not forget to visit the corresponding paragraphs of our online documentation, which has been updated, and is more accurate!
Sometimes, the on-demand synchronization is not enough.
So we have just introduced real-time replication via WebSockets.
For instance, you may need to:
- Synchronize a short list of always evolving items which should be reflected as soon as possible;
- Involve some kind of ACID-like behavior (e.g. handle money!) in your replicated data;
- Replicate not from a GUI application, but from a service, so use of a
TTimeris not an option;
- Combine REST requests (for ORM or services) and master/slave ORM replication on the same wire, e.g. in a multi-threaded application.
In this case, the framework is able to use WebSockets and
asynchronous callbacks to let the master/slave replication - see
Asynchronous callbacks - take place without the need to ask explicitly
for pending data.
You would need to use
TSQLRestServer.RecordVersionSynchronizeSlaveStop methods over the
proper kind of bidirectional connection.
The first requirement is to allow WebSockets on your
Master HTTP server, so initialize the
class as a
useBidirSocket kind of server - see
Network and Internet access via HTTP:
MasterServer := TSQLRestServerDB.Create(MasterModel,'master.db3'); HttpMasterServer := TSQLHttpServer.Create('8888',[MasterServer],'+',useBidirSocket); HttpMasterServer.WebSocketsEnable(Server,'PrivateAESEncryptionKey');
On the Slave side, the HTTP client should also be upgraded to support WebSockets:
MasterClient := TSQLHttpClientWebsockets.Create('127.0.0.1',HTTP_DEFAULTPORT,MasterModel); MasterClient.WebSocketsUpgrade('PrivateAESEncryptionKey');
Of course, the model should match for both
As the WebSockets protocol definition - here above the same
'PrivateAESEncryptionKey' private key.
Then you enable the real-time replication service on the Master side:
In practice, it will publish a
interface-based service on the server side - see
Client-Server services via interfaces.
Assuming that the slave database has been defined as such:
SlaveServer := TSQLRestServerDB.Create(SlaveModel,'slave.db3');
(in this case, the
SlaveModel may not be the same as the
TSQLRecordPeopleVersioned should be
part of both models)
Then you can initiate real-time replication from the slave side with a single line, for a given table:
The above command will subscribe to the remote
replication service (i.e.
IServiceRecordVersion interface), to
receive any change concerning the
table, using the
MasterClient connection via WebSockets,
and persist all updates into the local
To stop the real-time notification for this ORM table, you could execute:
Even if you do not call
the replication will be stopped when the main
will be released, and the
MasterServer be unsubscribe
this connection for its internal notification list.
The real-time notification details have been tuned, to consume as minimum
bandwidth and resources as possible.
For instance, if several modifications are to be notified on a slave connection in a short amount of time, the master is able to gather those modifications as a single WebSockets frame, which would be applied as a whole to the slave database, in a single BATCH transaction.
Feedback is welcome in our forum, as usual!