聊聊原美图开源的kv存储titan

小白debug 2023-09-05 09:02

市面上开源 kv 轮子一大堆,架构上都是 rocksdb 做单机引擎,上层封装 proxy, 对外支持 redis 协议,或者根据具体业务逻辑定制数据类型,有面向表格 table 的,有做成列式存储的

国内公司大部分都有自己的轮子,开发完一代目拿到 KPI 走人,二代目继续填坑,三四代沦为边缘。即使开源也很难有持续的动力去维护,比如本文要分享的 美图 titan[1],很多优化的 proposals[2] 都没实现,但是做为学习项目值得研究,万一哪天二次开发呢

整体架构

Titan 代码 1.7W 行,纯 go 语言实现。server 层只负责处理用户请求,将 redis 数据结构映射成 rocskdb key/value, 底层使用 tikv 集群

站在巨人的肩膀上,titan 无需考滤数据 rebalance, 不关心数据存储副本同步,这也是为什么代码量如此少

压测[3] 数据只有 2018 年的,性能一般,latency 也没区分 99 和 95 分位。如果基于最新版本的 tikv 集群测试效果可能更好

数据类型实现

目前数据结构只实现了 string, set, zset, hash, list, 有些也只是部分支持,只能说够用

持久化的 kv 轮子,难点就是如何把 redis 数据结构与 rocksdb key/value 做映射。原来单进程天然实现的原子性很难实现,维护一种数据涉及多个 key, 如果分布在多个 instance 进程又涉及了分布式事务,吞吐自然降低很多

比然我们常用 lua 脚本自定义一些业务逻辑,将涉及的多个 key 用 hash tag 处理下,变成同一个 redis slot, 但这在 titan 里是做不到的

性能问题,比如 HLEN 操作,本来 redis O(1) 操作,如果在 titan  的 hash metakey 中维护 len 记录,那么高并发写删 hash 时就会有大量冲突。再比如 zset 数据结构,zrange, zrangebyscore, zrangebylex 需要将 member, score 分别编码存储,用空间换时间

String

String 类型只有两种 key: MetaKey, ExpireKey

MetaKey 中 namespace 用于实现多租户隔离,但也只是逻辑上的,毕竟资源仍然是共用的,dbid 类似 redis db0, db1 ...

ExpireKey 用于主动过期数据,后台任务定期扫。每个类型都有,后面省略不表

MetaValue 前 42 字节为属性信息,后面才是真正的用户 value. 时间字段表示创建,更新,过期 timestamp, 被动过期时会检查 ExpireAt. uuid 用于唯一标识 key, titan 主动 GC 会用到

Type 表示数据类型

const (
 ObjectString = ObjectType(iota)
 ObjectList
 ObjectSet
 ObjectZSet
 ObjectHash
)

Encoding 表示具体的编码类型

const (
 ObjectEncodingRaw = ObjectEncoding(iota)
 ObjectEncodingInt
 ObjectEncodingHT
 ObjectEncodingZipmap
 ObjectEncodingLinkedlist
 ObjectEncodingZiplist
 ObjectEncodingIntset
 ObjectEncodingSkiplist
 ObjectEncodingEmbstr
 ObjectEncodingQuicklist
)

为了兼容,定义与 redis 一致

Set

MetaKey 与 String 类型一样,MetaValue 一共 50 字节,前 42 字节一样,后 8 字节维护集合 Set 成员数量信息。也就是说后续的 SCARD 是 O(1),但同时删除增加都要修改 MetaValue

DataKey 编码了 Set 唯一 uuid 与成员 member 信息,由于集合只需要成员 member, 所以 DatValue[]byte{0}

Zset

与集合一样,zset MetaKey/MetaValue 内容一样

DataKey 内容基本一样,DataValue 是 score 值,同时也维护了 score -> member 映射的 ScoreKey, 用于空间换时间方便 zrangebyscore 查询

Hash

注意这里 hash 的 MetaValue 并没有维护成员 Len 信息,所以当 HLEN 时要遍历 range 整个 data key 空间,为什么这么做呢?

titan 作者说 hash 写并发时会有大量的事务冲突,所以选择不维护。后来他们提出一个方案,对 MetaKey 拆分成多个 slot,尽可能减少冲突,同时还能提高 HELN 性能,不过后来也没实现

List

List 有两种结构,一个是 ziplist, value 是用 pb 将多个元素编码在一起, 另外一个是 linkedlist. 当前实现没看到 ziplist 到 linkedlist 的转换,其实对于持久化存储来说,只用 linkedlist 足够了

MetaValue 后 24 字节分别维护了 len, lindex 和 rindex, 其中 index 类型是 float64, 为什么不是 int64 类型呢?

原因在于对于 Linsert 操作,如果插入 (2, 3) 之间,那么会失败,但是用 float64 大概率会成功,但是考滤 float64 也有精度问题,存在失败的概率

// calculateIndex return the real index between left and right, return ErrPerc=
func calculateIndex(left, right float64) (float64, error) {
 if f := (left + right) / 2; f != left && f != right {
  return f, nil
 }
 return 0, ErrPrecision
}

DataKey 编码 index 信息,DataValue 就是值

事务冲突

由于 titan 整体都是小事务,所以对于 tikv 事务开启了 1PC 和 AsyncCommit, 来提高整体吞吐量。对于冲突的事务,titan 尽可能重试证执行成功

关于 affinity 亲缘性问题,titan 想将一个类型的 key 尽可能放到一个 tikv 实例中,当前没有实现,很难,不好搞。可以说 tikv 减少了持久化 kv 开发难度,也束缚了灵活性

删除 GC

Delete 时,删除 MetaKey,如果存在 TTL 那么删除 ExpireKey, 对于非 String,将 DataKey 扔到 sys namespace 中

$sys{namespace}:{sysDatabaseID}:GC:{datakey}

后台 doGC 调用 gcDeleteRange 慢慢删除,由于 DataKey 中存在 uuid, 基本不会重复,不影响用户重新创建相同 key

Flushdb 操作也非常重,理论上可以给所有 key 编码时带上 version, 这样可以快速 flush 快速回滚

运维周边

代码开源只是第一步,周边生态建设好用的人才多。目前看 tikv 运维 pingcap 有很多文档,基本够用了,做好参数上的调优

监控,故障处理,做好 chaos 故障注入测试

数据一致性校验,异构同步 redis 等等目前看都是缺失的

小结

目前 titan 的状态离真正 production ready 还差若干个 P0 故障,OOM 内存被打爆,spike 流量把集群打跨

代码还有些书写瑕疵,想要用的同学,有能力二次开发的做好集群压测,故障注入,限流,千万不要急于上线,随时做好回滚的准备

分享知识,长期输出价值,这是我做公众号的目标。同时写文章不容易,如果对大家有所帮助和启发,请帮忙点击在看点赞分享 三连


欢迎加我!


参考资料
[1]

美图 titan: "https://github.com/distributedio/titan",

[2]

优化 proposals: "https://github.com/distributedio/titan/tree/master/proposals",

[3]

titan benchmark: "https://github.com/distributedio/titan/blob/master/docs/benchmark/benchmark.md",


评论
  • 在物联网领域中,无线射频技术作为设备间通信的核心手段,已深度渗透工业自动化、智慧城市及智能家居等多元场景。然而,随着物联网设备接入规模的不断扩大,如何降低运维成本,提升通信数据的传输速度和响应时间,实现更广泛、更稳定的覆盖已成为当前亟待解决的系统性难题。SoC无线收发模块-RFM25A12在此背景下,华普微创新推出了一款高性能、远距离与高性价比的Sub-GHz无线SoC收发模块RFM25A12,旨在提升射频性能以满足行业中日益增长与复杂的设备互联需求。值得一提的是,RFM25A12还支持Wi-S
    华普微HOPERF 2025-02-28 09:06 143浏览
  • 1,微软下载免费Visual Studio Code2,安装C/C++插件,如果无法直接点击下载, 可以选择手动install from VSIX:ms-vscode.cpptools-1.23.6@win32-x64.vsix3,安装C/C++编译器MniGW (MinGW在 Windows 环境下提供类似于 Unix/Linux 环境下的开发工具,使开发者能够轻松地在 Windows 上编写和编译 C、C++ 等程序.)4,C/C++插件扩展设置中添加Include Path 5,
    黎查 2025-02-28 14:39 140浏览
  •         近日,广电计量在聚焦离子束(FIB)领域编写的专业著作《聚焦离子束:失效分析》正式出版,填补了国内聚焦离子束领域实践性专业书籍的空白,为该领域的技术发展与知识传播提供了重要助力。         随着芯片技术不断发展,芯片的集成度越来越高,结构也日益复杂。这使得传统的失效分析方法面临巨大挑战。FIB技术的出现,为芯片失效分析带来了新的解决方案。它能够在纳米尺度上对芯片进行精确加工和分析。当芯
    广电计量 2025-02-28 09:15 116浏览
  • 美国加州CEC能效跟DOE能效有什么区别?CEC/DOE是什么关系?美国加州CEC能效跟DOE能效有什么区别?CEC/DOE是什么关系?‌美国加州CEC能效认证与美国DOE能效认证在多个方面存在显著差异‌。认证范围和适用地区‌CEC能效认证‌:仅适用于在加利福尼亚州销售的电器产品。CEC认证的范围包括制冷设备、房间空调、中央空调、便携式空调、加热器、热水器、游泳池加热器、卫浴配件、光源、应急灯具、交通信号模块、灯具、洗碗机、洗衣机、干衣机、烹饪器具、电机和压缩机、变压器、外置电源、消费类电子设备
    张工nx808593 2025-02-27 18:04 120浏览
  • 更多生命体征指标风靡的背后都只有一个原因:更多人将健康排在人生第一顺位!“AGEs,也就是晚期糖基化终末产物,英文名Advanced Glycation End-products,是存在于我们体内的一种代谢产物” 艾迈斯欧司朗亚太区健康监测高级市场经理王亚琴说道,“相信业内的朋友都会有关注,最近该指标的热度很高,它可以用来评估人的生活方式是否健康。”据悉,AGEs是可穿戴健康监测领域的一个“萌新”指标,近来备受关注。如果站在学术角度来理解它,那么AGEs是在非酶促条件下,蛋白质、氨基酸
    艾迈斯欧司朗 2025-02-27 14:50 400浏览
  • RGB灯光无法同步?细致的动态光效设定反而成为产品客诉来源!随着科技的进步和消费者需求变化,电脑接口设备单一功能性已无法满足市场需求,因此在产品上增加「动态光效」的形式便应运而生,藉此吸引消费者目光。这种RGB灯光效果,不仅能增强电脑周边产品的视觉吸引力,还能为用户提供个性化的体验,展现独特自我风格。如今,笔记本电脑、键盘、鼠标、鼠标垫、耳机、显示器等多种电脑接口设备多数已配备动态光效。这些设备的灯光效果会随着音乐节奏、游戏情节或使用者的设置而变化。想象一个画面,当一名游戏玩家,按下电源开关,整
    百佳泰测试实验室 2025-02-27 14:15 137浏览
  • 振动样品磁强计是一种用于测量材料磁性的精密仪器,广泛应用于科研、工业检测等领域。然而,其测量准确度会受到多种因素的影响,下面我们将逐一分析这些因素。一、温度因素温度是影响振动样品磁强计测量准确度的重要因素之一。随着温度的变化,材料的磁性也会发生变化,从而影响测量结果的准确性。因此,在进行磁性测量时,应确保恒温环境,以减少温度波动对测量结果的影响。二、样品制备样品的制备过程同样会影响振动样品磁强计的测量准确度。样品的形状、尺寸和表面处理等因素都会对测量结果产生影响。为了确保测量准确度,应严格按照规
    锦正茂科技 2025-02-28 14:05 134浏览
  • 在2024年的科技征程中,具身智能的发展已成为全球关注的焦点。从实验室到现实应用,这一领域正以前所未有的速度推进,改写着人类与机器的互动边界。这一年,我们见证了具身智能技术的突破与变革,它不仅落地各行各业,带来新的机遇,更在深刻影响着我们的生活方式和思维方式。随着相关技术的飞速发展,具身智能不再仅仅是一个技术概念,更像是一把神奇的钥匙。身后的众多行业,无论愿意与否,都像是被卷入一场伟大变革浪潮中的船只,注定要被这股汹涌的力量重塑航向。01为什么是具身智能?为什么在中国?最近,中国具身智能行业的进
    艾迈斯欧司朗 2025-02-28 15:45 221浏览
  • 一、VSM的基本原理震动样品磁强计(Vibrating Sample Magnetometer,简称VSM)是一种灵敏且高效的磁性测量仪器。其基本工作原理是利用震动样品在探测线圈中引起的变化磁场来产生感应电压,这个感应电压与样品的磁矩成正比。因此,通过测量这个感应电压,我们就能够精确地确定样品的磁矩。在VSM中,被测量的样品通常被固定在一个震动头上,并以一定的频率和振幅震动。这种震动在探测线圈中引起了变化的磁通量,从而产生了一个交流电信号。这个信号的幅度和样品的磁矩有着直接的关系。因此,通过仔细
    锦正茂科技 2025-02-28 13:30 100浏览
  •           近日受某专业机构邀请,参加了官方举办的《广东省科技创新条例》宣讲会。在与会之前,作为一名技术工作者一直认为技术的法例都是保密和侵权方面的,而潜意识中感觉法律有束缚创新工作的进行可能。通过一个上午学习新法,对广东省的科技创新有了新的认识。广东是改革的前沿阵地,是科技创新的沃土,企业是创新的主要个体。《广东省科技创新条例》是广东省为促进科技创新、推动高质量发展而制定的地方性法规,主要内容包括: 总则:明确立法目
    广州铁金刚 2025-02-28 10:14 103浏览
我要评论
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦