spanner:
支持10~100 tps;
支持 push & pull 语义(即可作为 mq 使用);
架构:
如,ABC三个server,分别维护ab两个切片,三个server的a、b切片分别为两个paxos group管理;
主要挑战:
- 保证强一致性;
- 支持跨分片执行的事务;
- 只读和读写的事务需要做到串行化;
读写事务(无时间戳):
分片服务器维护的锁表不需要被复制(为了读事务的速度),即仅存在leader上,如果leader挂了,事务就需要重启了;
协调者也为一个paxos组(即2PC内的协调者的概念,高可用的);
协调者将写操作发给分片服务器后,他们的leader会先拿本地锁(注,是分片服务器,维护的数据没有交集),然后写WAL(同步paxos集群状态),成功后即返回yes(一阶段尾);
事务协调器提交事务(同步自己的集群),通知分片服务器提交,并释放对应的锁;
当分片服务器都返回ok后,事务协调器&分片服务器可清理回收有关状态;
只读事务:
无锁,无2PC,从本地的分片直接读取;
满足外部一致性,后执行的事务一定能观察到先执行的事务结果;
快照隔离:
为事务分配时间戳,读写事务的时间戳记录提交时间,只读事务的时间戳记录事务开始时间;
所有事务执行按照时间顺序进行,即保证只读事务不是读取最新数据,而是读取相对于只读事务开始时刻前的最新数据;(数据存储会将值和时间戳都记录下来,而不是直接覆盖);
为了避免读到分片集群中的旧数据(满足大多数,尚未同步完所有节点),规则:读取为时间戳x,则需要等待大于x的写入到达后,以及若有小于x的已经准备好的事务,则在返回读取值前需要提交,才可返回数据(此举是为了保证外部一致性);此举保证了不会读取过时数据(如果一直没有新写入,会返回错误);(raft 举例,就是读数据时等待一个心跳包到达后才允许判断并返回数据,防止分区或者落后等不一致问题)
时钟:
如果只读事务的时间戳偏大:会导致等待的时间变长(老师说不会出问题?好像有可能读到实际时间之后的数据啊,这样也违反外部一致性?);
偏小:明显读取的数据可能是过时的;
时钟偏移很常见,多服务器间的时钟很难保持一致;
故使用原子钟(同步全球时间)+GPS,定义一个时间戳的误差范围(平时都是一个时刻,现在是一个时间范围),earliest和latest,保证范围内的事务都是一致的(时钟越精确,范围越小);
前面的时间戳,赋值为范围的latest,即一定是在真实时间之后的(此举保证事务绝对顺序化,即每个事务都选择延后,不会读旧数据);
规则:此时读写事务被分配的时间戳为latest,则推迟提交直到请求时钟后的时间范围的earliest>原latest;