RavenDB Clusters & Write Assurances
RavenDB handles replication in an async manner. Let us say that you have 5 nodes in your cluster, set to use master/master replication.
That means that you call SaveChanges(), the value is saved to the a node, and then replicated to other nodes. But what happens when you have safety requirements? What happens if a node goes down after the call to SaveChanges() was completed, but before it replicate the information out?
In other systems, you have the ability to specify W factor, to how many nodes this value will be written before it is considered “safe”. In RavenDB, we decided to go in a similar route. Here is the code:
1: await session.StoreAsync(user);
2: await session.SaveChangesAsyng(); // save to one of the nodes3:
4: var userEtag = session.Advanced.GetEtagFor(user);
5:
6: var replicas = await store.Replication.WaitAsync(etag: userEtag, repliacs: 1);
As you can see, we now have a way to actually wait until replication is completed. We will ping all of the replicas, waiting to see that replication has matched or exceeded the etag that we just wrote. You can specify the number of replicas that are required for this to complete.
Practically speaking, you can specify a timeout, and if the nodes aren’t reachable, you will get an error about that.
This gives you the ability to handle write assurances very easily. And you can choose how to handle this, on a case by case basis (you care to wait for users to be created, but not for new comments, for example) or globally.
Comments
Would it be possible to have this inside a transaction, so it either saves and replicates to, say, 2 total nodes, or none?
Otherwise you save to one, but it may fail during the replication wait. What do you do then? The doc might have been saved, it's just that the node went down, so you'll see it later.
But what if I need to make sure it's saved on X nodes, or it isn't saved at all?
Mircea, No, that is not possible. If this is something that you need, you would need to write to the N nodes you want yourself in a DTC transaction. Note that we support this, but don't recommend its usage. It is very expensive.
If I'm reading tha same user from another master I can't be sure it's the current one right? Or it's a obvious condition and so a fallacy of my architecture?
Mauro, That depend on your actual topology. By default, replication is for HA. If you care for seeing the latest, you read from the master. If you don't care, you read from any node.
Will this only work with the Async methods? IE: StoreAsync, SaveChangesAsync.
Troy, Nope, you can call it from sync session as well. You would just need to call WaitAsync().Wait() to force it to physically wait.
Comment preview