复述是一个高性能分布式的键值数据库。它支持多种数据结构,并可应用于缓存,队列等多种场景下。使用过复述的小伙伴们可能对这些已经非常熟知了、下面我想来谈谈复述,也许并不被每个人了解的那点事。
刚看到标题你可能会说,我知道,不就是RDB和AOF嘛。这些已经是老生常谈了。那么我们今天就深入谈谈这两种持久化方式的逻辑和原理。
<强> RDB的原理强>
在复述中RDB持久化的触发分为两种:自己手动触发与复述,定时触发。
针对RDB方式的持久化,手动触发可以使用:
(1)节省:会阻塞当前复述,服务器,直到持久化完成,线上应该禁止使用。
引用>
(2)bgsave:该触发方式会叉一个子进程,由子进程负责持久化过程,因此阻塞只会发生在叉子进程的时候。
而自动触发的场景如下:
根据我们的拯救mn配置规则自动触发;
引用>
从节点全量复制时,主节点发送rdb文件给从节点完成复制操作,主节点会触发bgsave;
执行调试重载时处罚;
执行关闭时,如果没有开启aof,也会触发。
由于拯救基本不会被使用的到,我们来看看bgsave这个命令是如何完成RDB的持久化的。
(1)复述,调用叉,现在有父子两个进程
引用>
(2)子进程根据内存中的数据库快照,往临时文件中写入重建数据库状态的命令
(3)父进程继续处理客户请求,除了把写命令写入到原来的aof文件中,同时把收到的写命令缓存起来。这样就能保证如果子进程重写失败的话并不会出问题。
(4)当子进程把快照内容写到临时文件中后,子进程发信号通知父进程。然后父进程把缓存的写命令也写入到临时文件。
(5)现在父进程可以使用临时文件替换老的aof文件,并重命名,后面收到的写命令也开始往新的aof文件中追加。
需要注意到是重写aof文件的操作,并没有读取旧的aof文件,而是将整个内存中的数据库内容用命令的方式重写了一个新的aof文件,这点和快照有点类似。
复述,采用的是基于内存的单进程单线程模型的KV数据库,由C语言编写,官方提供的数据是可以达到100000 +的每秒(每秒内查询次数)。这个数据不比采用单进程多线程的同样基于内存的KV数据库Memcached差!原因如下:
1,完全基于内存,绝大部分请求是纯粹的内存操作,非常快速;
引用>
2、数据结构简单,对数据操作也简单,复述中的数据结构是专门进行设计的;
3,采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗CPU、不用去考虑各种锁的问题,不存在加锁释放锁的操作,也不可能出现死锁而导致的性能消耗;
4、使用多路I/O复用模型,非阻塞IO;
5、使用的底层模型不同,底层实现方式以及与客户端之间通信的应用协议不一样,复述,直接构建了自己的VM机制。
<强>多路I/O复用模型强>
多路I/O复用模型是利用选择、调查,epoll可以同时监察多个流的I/O事件的能力,在空闲的时候,会把当前线程阻塞掉,当有一个或多个流有I/O事件时,就从阻塞态中唤醒,于是程序就会轮询一遍所有的流(epoll是只轮询那些真正发出了事件的流),并且只依次顺序的处理就绪的流,这种做法就避免了大量的无用操作。这里“多路”指的是多个网络连接,“复用”指的是复用同一个线程。采用多路I/O复用技术可以让单个线程高效的处理多个连接请求(尽量减少网络IO的时间消耗)。
复述中的事务(事务)是一组命令的集合。事务同命令一样都是复述最小的执行单位,一个事务中的命令要么都执行,要么都不执行.Redis事务的实现需要多和执行两个命令,事务开始的时候先向复述,服务器发送多命令,然后依次发送需要在本次事务中处理的命令,最后再发送EXEC命令表示事务命令结束。
关于复述,你可能不了解的一些事