neon专题
最近看了很多文章,列出来并且介绍一下设计思路技术选取
整体设计与其说aurora,更像 论文Socrates: The New SQL Server in the Cloud (Sigmod 2019)
Architecture decisions in Neon
可以沉到对象存储
Neon - Serverless PostgreSQL - ASDS Chapter 3
所谓的aurora架构都是这个德性,读 page server,要牛逼点查,还要牛逼scan,写wal 服务,wal服务自动刷page
本身pg架构也是类似的多进程架构,这样改自然,也更容易堆到创业目标索要的性能指标
根本没啥区别
其他卖点
时空漫游 Point in time read point in time restore。这种场景还是非常需要的,多版本。
以前在华为某个mongo用户也要这种能力,给rocksdb加时间戳来达到类似的目的
怎么做到?LSN时间戳在LOG中
Why does Neon use Paxos instead of Raft, and what’s the difference?
这篇文章提到,用paxos不用raft,因为架构设计,要求wal服务能帮助复制,但raft没有这种东西
简单说就是raft的witness设计。这种witness其实就是抄的paxos的角色设计,只能说他们没有raft实践团队,选择搞paxos这种强度大的
Deep dive into Neon storage engine
主要设计
存储为了保持PITR,文件要存多版本,而不是快照级别的备份,文件版本是image+delta模式
pageserver只持有一部分,没有就从cloud拉,定期merge写回新的
存储还是LSM,只不过需要为了多版本,做LSN设计,特化一下,不合并版本
快照需求是短的周/月级别
- 存储不可变
两种数据 image和delta
- image : key-range - LSN - kvkvkvkvkvkvkv...
- delta : key - LSN-range - v1v2v3v4...
kudu也是这样的
- 写流程
safekeeper 的内存大部分都是日志,buffer长一些,异步刷数据给pageserver
是不是感觉有点眼熟,没错,当mq用,safekeeper拆出来就是利用paxos多写特性,不局限于pageserver个数。一般pageserver都是key-range模式
wal流刷到pageserver转成成delta文件,然后定期compact成image
- 读,直接走pageserver 指定LSN GetPage@LSN
如果page找不到从云上拉,然后image delta读一波
有点clickhouse read on merge那种感觉。读放大严重
但关系型基本上使用都是range,所以还好
我没有看代码,所以有点疑问:
- 怎么快速的定位image文件?内存中要维护所有key-range信息,然后二分/hash?
- hash slot可能快,但hash scan不友好吧
- 字典序的话,维护一个前缀bloom-filter?
- 二分?让我猜到了,还真是 BST
- 怎么维护delta文件?compact策略是什么?
- 如何快速定位到delta文件?感觉读性能很差啊
- 感觉要有单独的meta信息来维护delta 且能持久化,大概是hash(key) key-lsn-lsn-lsn-lsn这样,不然怎么快速定位到delta,挺好奇neon的解法。
- 一致性级别? 只读pageserver 不读wal 的话,肯定是stale读的,这种能接受吗?
- 还是说客户端指定bound read给一个LSN,读不到失败/等待
感觉有很多地方值得看看代码
Persistent Structures: Key to 2000x Speedup in Neon’s WAL Indexing
看起来有点抽象
黑条image 灰色长方形delta 红线表示读路径
读到黑条image算是快的,返回,读到delta比较复杂,要一直往下找,直到找到image为止,才能定位到具体的LSN,然后这个读,重建image
这显然涉及到一个delta叶子和image根的一个遍历问题
delta叶子是连续的,整个树是不可变只追加的,有点imm-hash-trie的感觉了
那就可以构造二叉搜索树,然后每次新文件都追加写一下二叉搜索树,这样每个版本都有一层bst
没错https://github.com/orium/rpds 他们用的就是这玩意
比如最上层可能是这样的
怎么构造的?
大概下面三个图的流程
这样做到针对LSN的漫游
我之前看到arangodb在raft上也使用immer flex-vector来做,应对log这种追加 寻根比对,确实是一个可以实践的方向
他们的探索
R-tree
最差ON 不可接受,这是内存计算啊
线段树
可能大家都不太懂线段树,能用,就是太复杂,
最终采用二叉搜索树了
https://github.com/neondatabase/neon/pull/2998
https://github.com/neondatabase/neon/blob/main/pageserver/src/tenant/layer_map.rs
感觉还可以仔细研究一下