天天看点

mysql redis es对比/梳理

数据存储方式

. mysql:

行存储, 存储结构分为聚簇索引(innodb)和非聚簇索引(myisam),均是采用b+树结构。

聚簇索引:

必有主键索引,主键索引的叶子节点存储了表的数据。非叶子节点都是索引关键字,但是不是记录数据或者数据地址。

可能会有二级索引,二级索引的叶子节点存储的是主键值(而不是行指针)。

(这样可以减少当前行移动时,二级索引的维护,但会让二级索引占用更多的空间)。

非聚簇索引:

主键索引和二级索引存储上没有任何区别,所有的节点都是索引,叶子节点存储的是索引+索引对应的记录的数据。

区别:

  1. 聚簇索引读一定范围的数据比较快。
  2. 聚簇索引主键和行数据会缓存到buffer中,用主键查数据更快
  3. 聚簇索引数据变更减少二级索引的维护工作。
  4. 插入速度严重依赖于插入顺序,聚簇索引更新主键代价高。
  5. 聚簇索引二级索引占用一些空间

redis

redis整个数据库统统加载在内存当中进行操作,定期通过异步操作把数据库数据flush到硬盘上进行保存。

持久化分为AOF和RDB两种,RDB生成快照文件,AOF日志记录命令。

提供了write和fsync两种方式写入内存。

es

https://zhuanlan.zhihu.com/p/33671444

倒排索引的方式存储。

主要是通过建立一个term index(trie树),这棵树不会包含所有的term,它包含的是term的一些前缀。通过term index可以快速地定位到term dictionary的某个offset,然后从这个位置再往后顺序查找(二分法查找term dictionary)。再加上一些压缩技术(搜索 Lucene Finite State Transducers) term index 的尺寸可以只有所有term的尺寸的几十分之一,使得用内存缓存整个term index变成可能。

mysql redis es对比/梳理
  • 为什么比mysql快?

    因为比mysql多了term index(存在内存中,以FST(finite state transducers)的形式保存)加快检索,从term index查到对应的term dictionary的block位置之后,再去磁盘上找term,大大减少了磁盘的random access次数。

对于mysql来说,如果你给age和gender两个字段都建立了索引,查询的时候只会选择其中最selective的来用,然后另外一个条件是在遍历行的过程中在内存中计算之后过滤掉。

  • es联合索引利用Skip List / bitset 合并。
每一行叫document,每个单词叫term,单词列表叫dictionary。存储的doc-id list叫posting-list(int的数组,存储了所有符合某个term的文档id)。

读写

mysql

  1. 二级索引查找到主键索引-查找到相关数据

  2. 如果主键连续,innodb顺序写io。如果乱序需要取出每条记录对应的物理block,会引起大量的随机io。(innodb提供了insert buffer,合并插入操作,改乱序为顺序)

Redis

  1. 读内存
  2. 写入到内存中,如果开了aof,aof会以日志的形式记录每个写操作。

    触发方式:有写操作就写、每秒定时写(也会丢数据)。

ES

  1. 查询倒排索引
  2. 先写入buffer,在buffer里的时候数据是搜索不到的;同时将数据写入translog日志文件。

    2)如果buffer快满了,或者到一定时间,就会将buffer数据refresh到一个新的segment file中,但是此时数据不是直接进入segment file的磁盘文件的,而是先进入os cache的。这个过程就是refresh。

    每隔1秒钟,es将buffer中的数据写入一个新的segment file,每秒钟会产生一个新的磁盘文件,segment file,这个segment file中就存储最近1秒内buffer中写入的数据。

    但是如果buffer里面此时没有数据,那当然不会执行refresh操作咯,每秒创建换一个空的segment file,如果buffer里面有数据,默认1秒钟执行一次refresh操作,刷入一个新的segment file中。

    操作系统里面,磁盘文件其实都有一个东西,叫做os cache,操作系统缓存,就是说数据写入磁盘文件之前,会先进入os cache,先进入操作系统级别的一个内存缓存中去。

    只要buffer中的数据被refresh操作,刷入os cache中,就代表这个数据就可以被搜索到了

  3. 数据写入 --> 进入ES内存 buffer (同时记录到translog)--> 生成倒排索引分片(segment)

    2、将 buffer 中的 segment 先同步到文件系统缓存中,然后再刷写到磁盘

数据一致性保证/容灾

单节点:

https://sq.163yun.com/blog/article/172546631668785152

mysql存在redo日志和undo日志。通过redo日志和checkpoint保证单机数据不丢失。

redo log记录了对实际数据文件的物理变更(数据文件的什么位置数据做了如何的变更)。

InnoDB也是采用了WAL(日志优先落盘)。

数据库down机回放log文件恢复。

多节点:

MySQL提供了master-slave和group replication 集群级别的容灾方案。

  • Master-Slave架构主要思路是:master负责业务的读写请求,然后通过binlog复制到slave节点.
  • 主从架构存在数据不一致的问题,所以MySQL5.7出现了Mysql Group Replication方案,mgr采用paxos协议实现了数据节点的强同步,保证了所有节点都可以写数据,并且所有节点读到的也是最新的数据。

单节点也是通过translog的方式恢复,多节点通过增加replica shard解决。

primary shard首先接收client端发送过来的数据,然后将数据同步到replica shard中,当replica shard也写入成功后,才会告知client数据已正确写入,这样就防止数据还没写入replica shard时,primary挂掉导致的数据丢失。

分布式

master-slave和group replication

  1. 主从同步,读写分离。

    Master会将数据同步到slave,而slave不会将数据同步到master。Slave启动时会连接master来同步数据。缺点是数据量很大的情况下,集群的扩展能力还是受限于单个节点的存储能力

  2. 数据分片模型

    可以将每个节点看成都是独立的master,然后通过业务实现数据分片。

    结合上面两种模型,可以将每个master设计成由一个master和多个slave组成的模型。

  • RedisCluster,存储单元化

    将所有存储区域划分为16384个slots(槽位),每个节点负责一部分槽位,槽位的信息存储于每个节点中。当客户端请求进来时候会拉去一份槽位信息列表缓存在本地,RedisCluster的每个节点会将集群的配置信息持久化到自己的配置文件中,所以需要引入一套可维护的配置文件管理方案,尽量做到自动化。

    槽位算法:

    RedisCluster 默认会根据key使用crc32算法进行hash得到一个整数,然后用这个整数对16384取模定位key所在的槽位。它还运行用户在key字符串里面嵌入tag将key强制写入指定的槽位。

    迁移:

  • 首先使用CLUSTER GETKEYSINSLOT 命令获取该slot中所有的key, 然后每个key依次用MIGRATE命令转移数据。
  • 数据转移完毕之后,正式将slot指派给新的节点

当有新的节点加入或者断开节点时,就会触发Redis槽位迁移。

当一个槽位正在迁移时候在原节点的状态为migrating,在目标节点的状态为importing。

原节点的单个key执行dump指令得到序列化内容,再向目标节点发送restore携带序列化内容作为参数的指令,目标节点接收到内容后反序列化复制到内存中,响应给原节点成功。原节点收到成功响应后把当前节点的key删掉就完成了节点数据迁移。

mysql redis es对比/梳理
mysql redis es对比/梳理
  1. Redis主库的灾备模式(Redis Sentinel)

    主节点down机的时候只能手动切换机器。所以redis引入了自动切换机器的哨兵架构模式。

    前提:

    首先哨兵服务单独部署,需要保证高可用。然后引入zookeeper等分布式协调组件,保证哨兵可以感知redis集群的状态。

    作用:

    哨兵负责监控主节点的监控状态,当主节点不可用时,自动选一个从节点切换为主节点。

    触发:

    客户端在请求主节点时访问失败,会通过Redis哨兵查询主节点的地址。

    成功后再将新的主节点列表缓存到客户端中。

    等故障主节点恢复后会作为一个新的只读从节点加入集群。

自己实现的分布式算法,类似raft。

提供分片功能,并且每个分片都有replica。写入时,replica shard会同步数据。

一台机器down机,replica shard会变成primary shard。

如果master down机,重新选主。