Skip to content

Instantly share code, notes, and snippets.

View ideawu's full-sized avatar
🎯

吴祖洋 ideawu

🎯
View GitHub Profile
@ideawu
ideawu / KV数据库引擎开发.md
Last active January 20, 2021 06:42
KV数据库引擎开发

原始(Instinct)

  • WAL
  • 每一次读取时, 扫描整个 wal

问题:

  • wal 无序, 只能顺序扫描
  • 数据存在多个版本, 所以必须扫描完整个 wal 文件
  • 数据多版本, 浪费空间
@ideawu
ideawu / 数据库引擎性能优化的本质.md
Created December 31, 2020 05:01
数据库引擎性能优化的本质

读优化

内存延迟是1, 磁盘顺序读延迟是10, 磁盘随机读延迟是100. 本质是将磁盘IO转化为内存操作, 或者将磁盘随机访问转化为磁盘顺序访问.

  • 历史: 基于历史热点统计
  • 预测: 基于排序后局部性原理预测

因为数据多版本的原因, 还需要减少访问次数.

  • 读放大: 最优的场景是每个数据只有1个版本
@ideawu
ideawu / 数据库事务的原子性与隔离性.md
Last active December 29, 2020 08:06
数据库事务的原子性与隔离性

数据库事务的原子性与隔离性

数据库事务的原子性并不仅仅是指写操作, 而且还包括读操作. 对于写操作, 众所周知, 原子性是指操作序列中的所有操作要么全部成功, 要么全部失败. 但多次读操作未必是指要么全部读到要么全部读不到. 如果不是 Snapshot Isolation, 那么两次读操作, 可能有其中一次读到旧值, 另一次读到新值. 但是, 读操作的原子性要求必须满足因果性. 当读到新值之后, 就说明事务中的所有写操作都已完成, 显然, 后续的读操作必须读到新值, 不能读到旧值.

Snapshot Isolation 有一个最大的问题, 那便是在创建快照的时候(可能隐式创建), 如何处理 pending 状态的资源, 如果不处理, 那么同一个事务的两个资源, 在快照中可能处于不同的状态(一个已提交, 另一个未提交), 也显然违反了原子性.

对于隔离性来说, 只有 Serializable 才是符合原子性的. Read Committed 违反了原子性, 因为大部分的数据库实现, 只判断资源的状态是否为 committed, 并没有向上追查资源所关联的事务对象(commit point)的状态, 显然会出现先读到新值, 再读到旧值的情况. 这种情况违反了因果关系, 也违反了一致性.

在 Read Committed 和 Repeatable Read 之间, 应该加入一级叫 Linearizable Read, 符合线性一致性, 符合因果关系(Causality), 符合原子性.

@ideawu
ideawu / Read Committed Violates Atomicity.md
Last active December 29, 2020 03:40
Read Committed 事务隔离级别破坏了原子性吗?

Read Committed 级别只提到不返回中间态的脏数据, 但没提到是否要保证原子性.

例如, 事务 1 更新了 2 条记录 a 和 b, 另一个事务 2 依次去读 a, b. 当读到 a 为新值时, 再读 b 是旧值. 从因果关系上说, 这里违反了事务原子性. 如果先读到 a 是旧值, 再读 b 是新值, 则没有违反.

https://www.sqlskills.com/blogs/paul/read-committed-doesnt-guarantee-much/

@ideawu
ideawu / TTL 处理 - 系统时钟和逻辑时钟.md
Last active December 25, 2020 03:53
TTL 处理 - 系统时钟和逻辑时钟

在分布式系统中, TTL 的处理不能依赖系统时钟, 而应该依赖逻辑时钟. 否则, 多个节点的数据会不一致.

当一个 key 过期时, 无论是系统内部发现, 或是系统外部发现, 都需要系统的所有节点先达到时间共识, 然后再删除. 通过外部工具显式地发送一个删除请求(需要 CAS), 也算是逻辑时钟的一种.

而且, 删除操作必须是一个原子操作.

@ideawu
ideawu / 事务与MVCC.md
Created December 21, 2020 09:51
事务与MVCC

除了维护对象的多个版本, 还要维护每一个版本在其它地方的引用. 例如, 对象有 score 属性, 按 score 维护了一个排序列表. 那么, 每一个版本都要按版本的 score, 在排序列表中创建一个 shadow.

@ideawu
ideawu / Fix Mac Terminal SSH LC_CTYPE.md
Created December 18, 2020 09:22
解决 Mac 终端远程 SSH 报错 LC_CTYPE
-bash: warning: setlocale: LC_CTYPE: cannot change locale (UTF-8): No such file or directory

修改 Mac 的 .bash_profile

export LC_ALL="en_US.UTF-8"
@ideawu
ideawu / Logs in Database Management System.md
Created December 12, 2020 03:16
数据库系统中的日志

日志(LOG, Journal)是持久化的核心, 是基础, 是必须.

根据日志的用途, 可以分成两类:

  1. Write Ahead Log, 将数据持久化在日志中, 日志持久化, 即代表数据持久化. 日志持久化之后, 后期再将数据转存到它们应该放的地方.
  2. Write Behind Log, Commit Log, 先将数据直接写到它们应该放的地方, 然后通过日志来确认.

WAL 在理想情况下, 单次写的延迟较小, 但有写放大问题, 因为必须有"转存"步骤.

WBL 单次写延迟大, 因为每一次写请求涉及两次持久化, 但没有写放大问题.

@ideawu
ideawu / 分布式系统的定义.md
Created December 11, 2020 11:19
分布式系统的定义

有很多软件假借分布式之名, 是伪分布式, 造成这个现象很大的原因是分布式系统的定义模糊不清. 我尝试定义分布式系统:

  1. share nothing
  2. co-operate

share nothing, 系统中存在多个独立的节点, 互相不知道其它节点. 某个节点可能知道存在着其它的节点, 但它不知道其它节点在哪, 有多少个. 即使知道在哪, 数量多少, 也不知道其它节点的内容.

co-operate, 协作. 节点之间遵循某种规则, 一起完成一项大的任务. 例如分布式数据库的 sharding, 不同的节点存在不同的数据, 它们数据之和成为一个整体.

根据这两项原则, etcd 不是分布式数据库, 只是一个多机多副本的单实例数据库, 也许可以称为单机数据库, 但它又确实使用了多机. etcd 的每一个节点都知道, 其它的节点的数据和自己的数据是完全相同的(应该如此). 所以, etcd 是伪分布式系统.