BigTable读后笔记
- GFS可能出现重复记录或者padding,Bigtable如何处理这种情况使得对外提供强一致性模型?
ANS: Bigtable写入GFS的数据分为两种: 1)操作日志,当Tablet Server发生故障时,它上面服务的子表会被集群中的其他Tablet Server继续提供服务,加载子表可能需要回放操作日志,每条操作日志唯一的序号,通过它可以去除重复的操作日志。
2)每个子表包含的SSTable数据,如果写入GFS失败可以重试并产生多条重复记录,但是Bigtable只会索引最后一条写入成功的记录。
- 为什么Bigtable设计成Root、Meta、User三级结构,而不是两级或者四级结构?
ANS:采用这种三层结构的存储模式,可以标识2^34 个 Tablet 的地址(如果每个 Tablet 存储 128MB 数据,那么一共可以存储 2^61 字节数据)。
- 读取某一行用户数据,最多需要几次请求?分别是什么?
ANS:客户程序使用的库会缓存 Tablet 的位置信息。如果客户程序没有缓存某个 Tablet 的地址信息,或者发现它缓存的地址信息不正确,客户程序就在树状的存储结构中递归的查询 Tablet 位置信息;如果客户端缓存是空的,那么寻址算法需要通过三次网络来回通信寻址,这其中包括了一次 Chubby 读操作;如果客户端缓存的地址信息过期了,那么寻址算法可能需要最多6次网络来回通信才能更新数据,因为只有在缓存中没有查到数据的时候才能发现数据过期
- 如何保证同一个tablet不会被多台机器同时服务?
ANS: Master将子表分配给某个Tablet Server服务时需要确保没有其他的TS正在服务这个子表。通过Chubby的互斥锁机制保证的,TS启动时需要获取Chubby互斥锁,当TS出现故障,Master需要等到TS的互斥锁失效,才能把它上面的子表迁移到其他TS上。
(row:string, column:string, timestamp:int64) ->string
map<RowKey, map<ColummnFamily:Qualifier, map<Timestamp, Value>>>
按字典排序。
数据在SSTable连续存放,可以满足随机读取和顺序读取两种需求。
按主键有序存储,每个SSTable由若干个大小相近的数据块组成,每个数据包含若干行。数据块的大小在8到64KB之间。
- minor、merging、major这三种compaction有什么区别?
minor每次都创建一个新的SSTABLE;
因为读操作可能需要合并来自多个SSTABLE的更新,通过定期在后台执行Merging合并文件,限制文件的数量。合并所有SSTABLE的Merging过程叫作Major,已经不包含已经删除的信息或数据。
Minor Compaction是为了防止内存占用过多,Merging和Major Compaction是为了防止文件个数过多。
为了提高读操作的性能,Tablet 服务器使用二级缓存的策略。扫描缓存是第一级缓存,主要缓存 Tablet服务器通过 SSTable 接口获取的 Key-Value 对;Block 缓存是二级缓存,缓存的是从 GFS 读取的SSTable的Block。对于经常要重复读取相同数据的应用程序来说,扫描缓存非常有效;对于经常要读取刚刚读过的数据附近的数据的应用程序来说,Block 缓存更有用(例如,顺序读,或者在一个热点的行的局部性群组中随机读取不同的列)。
- 如果tablet出现故障,需要将服务迁移到其它机器,这个过程需要排序操作日志。如何实现?
使用单个日志显著提高了普通操作的性能,但是将恢复的工作复杂化了。
为了避免多次读取日志文件,我们首先把日志按照关键字排序。
为了并行排序, 我们先将日志分割成64MB的段,之后在不同的Tablet服务器对段进行并行排序。这个排序工作由Master服务器来协同处理,并且在一个Tablet服务器表明自己需要从commit日志文件恢复Tablet时开始执行。
ANS:当 Master 服务器将一个 Tablet 从一个 Tablet 服务器移到另外一个 Tablet 服务器时,源 Tablet 服务器会对这个 Tablet 做一次 Minor Compaction。这个 Compaction 操作减少了 Tablet 服务器的日志文件中没有归并的记录,从而减少了恢复的时间。Compaction 完成之后,该服务器就停止为该 Tablet 提供服务。在卸载 Tablet 之前,源 Tablet 服务器还会再做一次(通常会很快)Minor Compaction,以消除前面在一次压缩过程中又产生的未归并的记录。第二次 Minor Compaction 完成以后,Tablet 就可以被装载到新的 Tablet 服务器上了,并且不需要从日志中进行恢复。
两次Minor Compaction
BT的子表的数据分成内存中的MemTable和GFS中的多个SSTable,由于BT中同一个子表只被一台TS服务,进行分裂也较为简单。BT上执行分裂操作不需要进行实际的数据拷贝工作,只需要将内存中的索引信息分布两份。分裂之后两个子表各自写不同的MemTable,等到执行Compaction操作时再根据分裂后的子表范围生成不同的SSTable,无用的数据自然成为垃圾被回收。另外,用户表的分裂需要修改元数据表,元数据表的分裂需要修改根表。
合并操作由Master发起,相比分裂操作要更加复杂,由于待合并的两个子表可能被不同的TS加载,所以第一步需要迁移其中一个子表,以使它们在同一个TS上,接着通知TS执行子表合并。