专家观察 | 林尚泉:“小米结构化存储系统及融合云平台的设计与(2)
我们是通过HBase Coprocessor来实现了indexObserver,也就是客户发送Put或Delete请求后我们会拦截这个操作,然后再计算要上出来索引,再把它放到原来的数据里,最后再同一台机器上一起落地,就可以保证原数据和索引数据的原子性. 还支持了多种类型的局部二级索引,其中包括EAGER类型,也就是更新删除时同时删除失效索引,是适合写少读多的场景,而LAZY索引是读取判断索引有效性,更新时不做额外操作,适合写多读少,还有IMMUTABLE是需要用户保证数据的只读性,就适合以只读数据的一次性写入,读写都不需要做额外的判断,这种比较高效. 还支持了全局二级索引,和局部二级索引不一样的地方是它的索引数据是单独的存在一个HBase表里,我们采用了谷歌的percolator方案实现的,我们在hbase上实现了这套算法叫Themis,这个已经开源,这个算法可以保证跨表更新的原子性,Chronos为全局单调递增时间戳. 全局二级索引数据对应的HBase的KeyValue跟局部二级索引不大一样,是以索引键排在最前面,再到实体组键和主键,我们对局部二级索引和全局二级索引做了一下性能对比.这个图是对某一张表建立了一个全局二级索引和局部二级索引,然后再写,红色是局部二级索引,蓝色是全局二级索引 可以看到因为全局二级索引会涉及到分布式的事务,可以看到性能损耗比较大,局部二级索引比它有好个四倍左右,而读的话同样局部二级索引好个两倍. 另外我们实现了stream功能,如果开了这个功能,用户对表的修改除了在原来的数据CF上写,还会封装成一条消息在另一个CF里再写一份,另外起一个MR job定期扫那个额外的CF,再把那个消息打到流式消息队列里,用户就会拿到流式消息队列来消费这些数据. 其中包括两种类型,一个是RECORD IMAGE,得到的消息是这行数据被修改以后最后的视图,用户拿着这种类型的消息就可以做一些最终一致的增量备份,另外是MUTATE LOG,就是每一行的修改日志,这种类型再结合一个定期打快照的功能,就可以把指定某一个表恢复到历史任意一个时间点. 我们采用了facebook 的Thrift框架,对外屏蔽了一些复杂的配置,由于是使用了Thrift框架,很方便的可以支持多种语言的SDK. ThriftServer主要对外提供一个无公网的http服务,对外屏蔽了HBase,用户只需要拿到一个域名就可以直接访问,简化了认证和配置,支持了多种语言的SDK,多租户包括访问控制和流量控制. ACL功能,我们是在HBase那里存了一份元数据表,它的格式是某一个表有哪些ACL信息,并且每一个节点会对元数据做本地缓存,假如有用户发了一个修改ACL的请求,这个ThriftServer不仅要更新元数据表,还要在Zookeeper修改一个节点,因为所有的ThriftServer节点都监听了Zookeeper的那个节点,就会收到一个通知进行更新,通过访问元数据表更新本地缓存. 流量控制,SDS支持用户每一个表进行预设置的读写配额,设置读写配额的时候SDS会检查一下集群的能力,集群的能力是根据我们的一些性能测试得到的,做限流的时候是基于token bucket算法进行限流的,集群能力使用到80%的时候会提醒我们进行集群扩容.还实现了软删除的功能,因为要保证数据安全, 软删除就是用户发一个删表请求,要删除一张表的时候,SDS后台会先对这个表打一个快照,然后再去删除这个表,这个时候会存一堆snapshot文件,在经过TTL 的时间后删除,在删除之前用户可以通过restoretable通过clonesnapshot把表恢复出来. (编辑:ASP站长网) |