Strong Consistency with Raft and SQLite
blog.sqlitecloud.io
blog.sqlitecloud.io
The advantage you undeniably get is durability/high availability.
> Scalability: Distributed databases can be scaled horizontally by adding more nodes to the network, making handling larger amounts of data and higher volumes of requests easier.
This is only possible if you have a data partitioning scheme, right? But data partitioning is sort of a different problem from consensus/HA, right? If you do the simplest version of a consensus + database implementation, every disk on every instance of the consensus cluster is basically identical. So you don't benefit in that simple approach from adding more disks. It potentially just makes write latency worse unless you do flexible quorums so the quorum size is independent of the number of nodes in the cluster?
> Localized access: With a distributed database, data can be stored closer to the users who need it, which can improve response times and reduce network latency.
This would also only be true if you relax consistency requirements, right? If you need to be at the highest level of consistency you must send reads through consensus too otherwise if you read from the node nearest you it may be out of date.
It would be cool to see some numbers about the difference between latency of reads/writes in sqlitecloud and sqlite on a single node! It would help my intuition anyway.
So you don't benefit in that simple approach from adding more disks.
Not sure about this DB, but that's my understanding of consensus as well. The more nodes, the less likely any one going down harms things but the harder it is to reach consensus. You have to write to more places. It becomes slower not faster.Flexible quorums deals with this in the usual read/write case. But yeah leader election then becomes the bottleneck. So if the cluster is unstable overall performance gets even worse as you scale number of nodes.
For every shard you pick a few nodes, and you run consensus between those. This is the way Elasticsearch, CockroachDB, ... work.
So if a specific shard is getting writes from a specific region, you can easily move that shard to nodes in that region.
In contrast, etcd runs consensus over the whole cluster. So it is very safe, very slow, and meant for small datasets. In many ways, it is not a database, but a metadata store for distributed systems.
you require every write to be acknowledged by 3 nodes for consistency
How would that work? Someone else could get a different 3 nodes and write the same key, so they wouldn't read my write before writing their own? This isn't my area but I would assume the data has to be sharded ahead of time, not just write to any 3 out of 50 nodes that are closest to me.nah, you have leases (a time-limited and often renewable lock). so like your leader gets elected through consensus and then for the next N miliseconds, you have a garauntee that nobody else can be leader. this means your reads dont need to go through consensus. (hand-waving a lot of the details here.)
- A given row of data is configured to have N replicas, e.g. 3, 5, etc, but N doesn't have to equal the actual size the database cluster. e.g. you can have a database cluster of 21 nodes with N being 3. N represents the "Raft cluster size" and the database is composed of many "Raft clusters" that are responsible for segments of the data space. You can horizontally scale the size of the database cluster by adding more nodes and thus more "Raft clusters"
- Raft/Paxos are used to ensure linearizable writes to those replicas through a leader
- Multi row/partition transactions are handled through a different kind consensus called atomic commit/2 phase commit that's orthogonal to Raft/Paxos consensus: https://timilearning.com/posts/mit-6.824/lecture-12-distribu...
- Systems like Spanner, Cockroach have higher write latencies because replicas in Raft cluster have to achieve quorum consensus, but reads latency can mostly not be affected by always reading from the leader of a cluster via things like leader leases.
I agree with you about horizontal scalability in general though, the data isn't being partitioned. I guess read heavy loads can be scaled.
Would be interesting to see a breakdown of the differences.
https://www.philipotoole.com/9-years-of-open-source-database...
https://www.philipotoole.com/replicating-sqlite-using-raft-c...
https://www.philipotoole.com/rqlite-v3-0-1-globally-replicat...
The post makes a fairly big point of the shortcomings of statement-based replication (like what rqlite does).
What they state is correct -- non-deterministic SQL will be a problem, but it's not a difficult problem to solve. Just parse and rewrite the SQL statement before sending it to Raft. It's exactly what rqlite does[2] (though there is more to do). However they claim that there are two concerns with this approach.
>This solution introduces a runtime delay because each SQL statement must be parsed and analyzed.
The delay is insignificant compared with the delay introduced by Raft consensus. This is not a valid concern. I'm surprised they even mentioned it.
>More importantly, it increases the difficulty of staying up-to-date with the new versions of the underline SQL engine (SQLite in this specific case) because the custom parser must be updated each time a new SQL function/feature is introduced.
Theoretically somewhat true, but not true in practice. Any competent programmer can update any parsing code in a matter of hours. Also just because a new feature is introduced does not mean that the parser needs to be rewritten. That's because SQLite will not introduce breaking changes into their SQL specification. Any parser needs to be updated only if you want to support any new, non-deterministic feature.
Is that supposed to still apply when a small cluster (eg three nodes) is reduced to a single node? eg during node failures, maintenance, node failures during maintenance ;), etc.
When I was trying rqlite last week - eg prototyping a new SQLite "cloud" offering for DBHub.io - a remaining single node would consistently refuse to elect itself as the leader. Using default settings for everything.
Tried it out several times, though I didn't give it more than a minute or two to get itself happy.
Anyway, had to go with an initial non-RAFT approach for the prototype, but will likely investigate rqlite again in the future if I was just doing something dumb / fixable with tweaking. :)
However if you create a 3-node cluster (or add 2 nodes to an existing single-node cluster) then at least a quorum of nodes (N/2 +1) must be up and running for the cluster to be available. That's the way Raft works -- Cockroach, etcd, Consul -- all of them will work the same way.
So in your case a 3-node cluster with 2 nodes subsequently going down (or deliberately taken offline) is a cluster which is offline.
There is extensive documentation available on clustering, which you should review:
It's just it wasn't clear from the initial docs I saw that a 3 -> 1 cluster would be considered any differently. Clearly, an error on my part. :)
I'll circle back to rqlite in a while, after I get this existing prototype code rolled out and see what people make of it. Hopefully it turns out to be useful for people.
https://rqlite.io/docs/clustering/general-guidelines/#recove...
While this talks about "dealing with failure" using the config file described above basically allows you to force the cluster into any configuration you want (including a single-node cluster).
https://rqlite.io/docs/faq/#how-can-i-change-my-multi-node-c...
The code is open source, but the name is a registered trademark. Similar issue here: https://github.com/vapor/sqlite-kit/issues/47
I get there are some things are nondeterministic, but I'm surprised that they couldn't be converted into deterministic commands before sending them out. E.g. send the result of `RANDOM()` instead of the call itself.
I don't know how much that would buy you, but I'd imagine it might make the amount of information to send much smaller.
I couldn't find information on the maximum DB size, maximum number of connections, network throughput, datacenter locations and other basic information. The screenshot on the homepage clearly shows that there is a disk and CPU limitation.
It looks like this is a database with an SQLite API but internally it could be anything.
Anyone know how this compares to the work done by litestream: https://litestream.io/how-it-works/
Is this a fundamentally different idea: consistency vs. replication?
From the Litestream page: https://litestream.io/alternatives/#raft-based-consensus
The architecture is very similar.
Is there a plan to Open Source the server side code as well? :)