Open xumengpanda opened 4 years ago
We are debating two designs:
Client + Proxy locking. All proxies keep the locked ranges in memory and in sync such that for every transaction, if there are mutations read or modify keys in these locked ranges, the transaction is marked as failed. To reduce the work on the Proxies, each client caches the set of locked ranges so chat each client transaction can check locally without sending transaction data over. The cached ranges can be invalidated by a version (the mechanism is similar to metadata version key) piggybacked by the GRV response. If the version is obsolete, the client needs to retrieve the locked ranges from Proxies.
Resolver + StorageServer locking. The locked ranges are kept in all resolvers such that for every transaction, if there are mutations change keys in these locked ranges, the transaction is marked as failed. For read only transactions, locking in resolver alone is not enough. That is, the locked ranges should also be present on all storage servers so that reads for keys within these ranges can be failed.
The contract we want to maintain is that: for a lock transaction T_L
with a commit version C
T
committed before C
won’t see the effect of T_L
, thus can proceed to commit.T
started after C
will see the effect of T_L
, thus may fail due to locking.TODO lists after #3856 is merged:
Can we lock a key range in a DB while still allow clients operate on the other key ranges?
Two scenarios can benefit from this: 1) If data corruption happens at a small key range, say [b, c), the cluster can still serve traffic in the rest of key space, while we are restoring the data in [b, c).
2) If someone wants to move data in a small key range, say [b, c), from a live cluster A to another live cluster B, we can only lock that key range while still allow both clusters to serve traffic to the rest of key space.
The implementation is similar to Issue https://github.com/apple/foundationdb/issues/1044, except that we don't have to distinguish read and write lock.