Async online schema change 读书笔记

F1 中在线异步Schema变更

Online, Asynchronous Schema Change in F1

简介

F1 的主要特性影响到schema变更的地方有:

  1. 大量的分布
  2. 关系型schema,每个F1服务都有schema的一份拷贝,变更必须让所有的F1服务更新,相当于一次分布式的变更。
  3. 共享的数据存储,F1可以访问所有存储在spanner中的数据。
  4. 无状态服务,F1服务必须容忍机器故障,被取代,丢失网络。所以是无状态的,客户端可以随意连接到任何一个F1。
  5. 没有全局成员关系,F1服务之间没有通信关系。

在F1上进行Schema变更的要求:

  1. 所有数据的可访问性,不能因为schema变更而导致系统下线,哪怕是一部分数据库下线都是不可接受的。(比如锁住一个列)
  2. 最小化性能影响,频繁的schema 变更,要最小化性能的影响,即对用户响应时间的影响。
  3. 异步schema变更,因为F1之间没有通信协议,所以不能通过F1服务之间通信来同步schema。意味着,不同的F1服务可能使用新的schema在不同的时间点上。

背景

F1提供了一个建立在key-value数据上的关系的视图。
key-value store提供三种操作,put,del,get。
put和del insert或者delete一个给定的key。
get获取前缀符合给定key的数据集合。

F1 提供了乐观并发控制,会给key-value添加两个需求。

  1. Commit timestamps(提交时间戳)。每个key-value对有一个最后修改时间戳。
  2. 多个get和put可以被以原子的方式执行。

F1 的schema是一系列表的定义,每个表的定义由一组列、一组耳机索引、一组完整型约束,和一组乐观锁。列可以是原始类型或者复杂类型,主键的类型被严格要求只能是原始类型。在每一行中,列的值可以是缺省的,也可是是必须存在的。使用required标识。

F1 使用一种基于时间戳的乐观并发控制,与Percolator相似。F1 的schema包含一个额外的元素在每个表上,即乐观锁。
一个表可能有多个锁,每个列关联一个确切的乐观锁。每个行有它自己的乐观锁实例基于schema的定义,且这些实例控制了对这些行中的列的事务并发访问。

F1实现行级别的锁,用户可以给表添加新的锁并关联它到一个任意的列中。F1的用户可以选择锁的粒度,可以是行级别的范围锁到列级别的锁。

Schema 是一个特殊的k-v对来表示的。通过一个版本来表示当前的schema版本,当该标本变化的时候,表示有schema变更发生了。

不同的服务使用的新schema的时机不同,同一时刻可能存在多个版本的schema在是使用。

当所有的F1服务都加载了新的schema完成的时候,表示schema change已经完成。

造成数据损坏的主要原因是由于schema变化太过突然了。一部分F1使用旧的,一部分使用新的schema造成了数据损坏。

(PS:通常情况下,一步解决不了问题,就可以拆成若干步来完成。一阶段不行就两阶段,三阶段,直到问题解决,每一阶段都使问题缩小化,朝着最终的目标前进即可解决)

因此,引入中间状态,将一次危险的schema变更,拆解成一系列安全的schema变更。

为了简化正确的实现,F1允许最多不超过2个schema版本在使用。意味着,存在一个短暂的时间窗口,有两个schema版本在使用。超过两个版本的存在会大大引入复杂性。

Schema变更

F1的schema有表、列、索引、约束和乐观锁。称为schema项。每个schema项目都有与之关联的状态。有两种没有中间状态的称为:absent和public。

  • absent:当一个schema项不存在的时候,它是缺省的。
  • public:当一个schema项存在,并且可以影响或者被所有操作应用的时候,它是public的。

F1也存在两种内部的,中间的状态: delete-only 和 write-only。

  1. Definition 1:delete-only:一个delete-only 表、列、索引 不存在可以被用户读取的对应的k-v对。并且,如果 E 是一个表或者列,它仅仅可以被删除操作修改。如果E是一个索引, 它仅仅可以被delete和update操作修改,并且,update操作只能删除k-v对(当更新索引时),但不能创建新的k-v对。

  2. Definition 2:write-only状态是为列和索引定义的,write-only:一个write-only的列或索引可以允许insert、delete和update操作修改k-v对,但是任何上述的k-v对都不能对用户的读可见。因此,write-only状态允许数据被写入,但不允许读取(就索引而言,F1服务不使用write-only的索引去加速寻找。)

  3. Definition 3:write-only状态也定义了约束,write-only 约束:write-only 约束对于新的 insert、delete和update操作生效,但是它不保证对于所有已存在的数据也保持。

  4. Definition 4:一个数据库d在schema S下是遵守一致性的,当且仅当:

    1. 不存在没有表和行的列数据存在
    2. 所有的数据行都必须存在必须存在的列数据
    3. 不存在表结构中没有索引的索引数据项
    4. 所有对外可见的索引必须有所有数据的完整的索引项
    5. 所有的索引项目必须指向合法的行数据
    6. 所有对外公开的约束必须是被遵守的
    7. 不存在未知的数据
  5. Definition 5:一次schema变更,从S1 到 S2 是一致性保持的,当且仅当对于任何数据库d,要一致性遵守包括S1和S2

    1. 任何在S1下的操作,要维护遵守数据库d在S2下的一致性。
    2. 任何在S2下的操作,要维护遵守数据库d在S1下的一致性。

数据库的一致性

F1服务将强制新的操作满足约束,但读操作可能看到违背约束。

确保所有的F1服务对于数据库都有一个一致性视图是至关重要的。

  1. 不允许有孤儿数据。
  2. 不允许有违反完整性约束的数据。

添加或者删除schema element

可选结构化项

  1. 添加:absent -> delete only -> public
  2. 删除:public -> delete only -> database reorganization -> absent

按照上述的schema状态流程做schema变更,所有操作都会避免产生孤儿数据。并且由于添加的schema结构是可选的,所以也不存在完整性异常。

删除时候使用 database reorganization 来对列数据进行回收,清除那些删除掉的列对应的kv对。

必需的结构化项

  1. 添加:absent -> delete only -> write only -> database reorganization -> public
  2. 删除:public -> write only -> delete only -> database reorganization -> absent

对于约束

  1. 添加:absent -> write only -> public
  2. 删除:public -> write only -> absent

实现

  1. GC:对于删除列或者索引等,可以使用异步的GC机制来优化 database reorganization 阶段。通过异步删除,加快DDL的进度。
  2. Write fencing:写栅栏,Schema需要有Lease机制,不允许那些超过Lease的Schema的事务进行提交,以避免数据完整性被违反、或者有孤儿数据。每个Schema都存在一个版本号与之对应,当事务将要提交的时候,通过与内存中的Schema 仓库的接口进行校验,如果事务开始时使用的schema版本已经过时了,则该事务不能提交。必须重试。

F1使用了单独的Schema变更进程。通过版本控制仓库来保存schema变更记录,schema变更进程按照版本控制的更改记录进行schema变更,使其按顺序生效。

不变式:

如果schema S 在时间点t0 写入了,并且没有其它 schema 在 t0 -> t1 之间写入 (t1 > t0 + lease_period ),因此,在 t1 时刻,每个F1服务要么使用 S,要么不允许事务提交。

续Lease根据经验,一般在Lease过半的时候进行续Lease,续Lease的方式,通过周期性地重新读取schema从一个众所周知的位置在k-v store中。如果F1服务没办法续lease,则自行terminate。一般情况下,会再次拉起来,拉起来的时候会获取最新的schema。

对于执行Schema变更的进程,每个状态必须等待Lease时间之后,才能进行下一步状态,尽可能保证所有F1都使用到了最新的Schema。

续Lease可以优先检查Schema 的commit ts是否有变更,没有变更则不重新Load schema。有变更则才重新Load。

Data reorganization,数据重组

  • 数据重组必须支持暂停/恢复,并且过程是需要幂等的。
  • 在重组期间,所有的数据都是必须可以访问的。因此,重组过程,必须能够容忍并发的访问修改的数据。
  • 减少不必要的数据写入。当用户的事务已经写入了需要重组的kv对时,重组执行时就不需要写入。

F1使用了MapReduce的框架的思路,MapReduce控制器将待重组的数据进行分组,将分组信息给到map 任务,map任务扫描分组内所有的行,使用一个快照时间戳(这个时间戳应该是重组执行的时候获取的)。更新每一行遵从新的schema。取决于对应的schema变更操作,可能添加key或者移除。

每个map任务读取每一行并确定它是否已经被用户事务更新过了。如果用户事务更新过了,则map任务不需要更进一步修改行。遵循了Thomas写规则。

The End;

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,753评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,668评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,090评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,010评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,054评论 6 395
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,806评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,484评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,380评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,873评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,021评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,158评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,838评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,499评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,044评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,159评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,449评论 3 374
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,136评论 2 356

推荐阅读更多精彩内容