🎗️

中间件

Redis

  • redis cluster采用分布式hash计算处理节点
  • 数据库和缓存如何保证一致性?
    • 如果选择更新而不是删除缓存则一定需要加分布式锁
    • 先更新数据库再通过数据库日志异步删除缓存(业务解耦,不使用中间件而是单独的缓存服务,根据数据库日志构建缓存,维护热更新)
    • 根据CAP理论,双写很难同时保持A和C,加入缓存意味着放弃C加强A,不适合强一致性系统
    • 分布式事务也可以解决这个问题:https://dtm.pub/practice/theory.html,例如两段式或者三段式提交。如XA分布式事务

Mysql

  • mysql存储引擎实现
    • MyISAM的B+树索引叶子节点直接存储数据指针
    • InnoDB的B+树索引叶子节点存储主键,需要拿着主键再去查找
  • 导致索引失效的场景
    • 对索引使用左或者左右模糊匹配 (某些情况会被优化成走索引)
    • 对索引使用函数
    • 对索引进行表达式计算
    • 对索引隐式类型转换
    • 联合索引非最左匹配
    • WHERE 子句中的 OR
  • select默认属于快照读,通过MVCC实现,不会加锁,如需要加锁则需另加FOR UPDATE
  • InnoDB 存储引擎的默认事务隔离级别是「可重复读」
  • Mysql中行级锁依赖索引(因为是堆索引加锁,而不是数据),所以WHERE查询内容需要确保有索引
  • Mysql会对范围查询加间隙锁 ⇒ Gap Lock
  • 行锁也称为Record Lock
  • Next-key Lock = Record Lock + Gap Lock,select * from where .. for update会加这个锁
  • Mysql默认为Row-Level Lock,也就是只锁住选中的记录,如果WHERE无索引则锁表
  • Mysql事务采取两阶段提交,begin并不意味着事务的开始,只有当显示增删查改时或者使用for update才会开始事务
  • Mysql索引分为主键索引和二级索引(普通索引),命中二级索引时也会对对应的主健索引加锁
  • Mysql的可重复读依赖Read View, Read View是一个类似MVCC但是不完全相同的设计。导致了如下问题:
    • Mysql的事务在只有read-only queries时表现为可重复读事务级别
    • Mysql的事务在有write queries时表现为读已提交级别

Tidb

Tikv

  • Tikv是行式存储,TiFlash是列式存储

Clickhouse

Databend

Leveldb

  • 保证顺序写, 不删除数据只追加
  • 适用于写多读少 (SSTable一层一层往下找很慢)
  • 内存中使用skiplist建立MemTable的索引
  • Compaction容易导致读放大, 写放大, WiscKey旨在解决写放大问题
组成部分
  1. WAL
  1. MemTable (Mutable vs Immutable), Leveldb只会维护最多一个MemTable, ImmutableMemTable
  1. Tiered SSTable (compaction), 上层数据新, 下层数据旧
  1. TableCache, BlockCache, BloomFilter
  1. SSTable的索引文件, 存储每个key对应的offset
  1. Segment, SSTable由很多小的有序的segment组成, compaction是对segment的多路归并

Rocksdb

Etcd

Elasticsearch

Kafka

Kafka为什么这么快?
  1. 顺序写入
  1. 零拷贝技术
  1. partition分区, 支持横向扩展
  1. page cache

Spark

HDFS

Ceph

Arrow

 

Nginx

  • nginx默认支持consistent hash
  • nginx默认支持漏桶限流
  • nginx默认fork子进程而不是线程
  • 多个进程共同监听socket