redis
reids:读110000次/s,81000次/s
为什么可以这么快?
- 完全基于内存,绝大部分请求是纯粹的内存操作,非常快速。数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1);
- 数据结构简单,对数据操作也简单,Redis中的数据结构是专门进行设计的;
- 采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗
CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗; - 使用多路I/O复用模型,非阻塞IO;
- 使用底层模型不同,它们之间底层实现方式以及与客户端之间通信的应用协议不一样,Redis直接自己构建了VM 机制,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求;
多路 I/O 复用模型: 多路I/O复用模型是利用 select、poll、epoll 可以同时监察多个流的 I/O 事件的能力,在空闲的时候,会把当前线程阻塞掉,当有一个或多个流有 I/O 事件时,就从阻塞态中唤醒,于是程序就会轮询一遍所有的流(epoll 是只轮询那些真正发出了事件的流),并且只依次顺序的处理就绪的流,这种做法就避免了大量的无用操作。
这里“多路”指的是多个网络连接,“复用”指的是复用同一个线程。采用多路 I/O 复用技术可以让单个线程高效的处理多个连接请求(尽量减少网络 IO 的时间消耗),且 Redis 在内存中操作数据的速度非常快,也就是说内存内的操作不会成为影响Redis性能的瓶颈,主要由以上几点造就了 Redis 具有很高的吞吐量。
redis主从复制的原理
主从同步的策略
主从刚刚连接的时候,进行全量同步;全同步结束后,进行增量同步。当然如果有需要,slave 在任何时候都可以发起全量同步。redis 策略是无论如何首先会尝试进行增量同步,如不成功要求从机进行全量同步。
全量同步
发生的时间:
一般发生在slave初始化的阶段,这是slave需要将master上的所有的数据都复制一遍。
步骤:
- slave服务器连接master服务器(slaveof host port),发送SYNC命令;
- master服务器接收到SYNC命名后,开始执行BGSAVE命令生成RDB文件并使用缓冲区记录此后执行的所有写命令;
- master服务器BGSAVE执行完后,向所有slave服务器发送快照文件,并在发送期间继续记录被执行的写命令;
- slave服务器收到快照文件后丢弃所有旧数据,载入收到的快照;
- master服务器快照发送完毕后开始向slave服务器发送缓冲区中的写命令;
- slave服务器完成对快照的载入,开始接收命令请求,并执行来自master服务器缓冲区的写命令
实现逻辑
master服务器会开启一个后台进程用于将redis中的数据生成一个rdb文件,与此同时,服务器会缓存所有接收到的来自客户端的写命令(包含增、删、改),当后台保存进程处理完毕后,会将该rdb文件传递给slave服务器,而slave服务器会将rdb文件保存在磁盘并通过读取该文件将数据加载到内存,在此之后master服务器会将在此期间缓存的命令通过redis传输协议发送给slave服务器,然后slave服务器将这些命令依次作用于自己本地的数据集上最终达到数据的一致性。
增量同步
发生的时间:
slave初始化后开始正常工作时master服务器发生的写操作同步到从服务器的过程;
实现逻辑
从redis 2.8版本以前,并不支持部分同步,当主从服务器之间的连接断掉之后,master服务器和slave服务器之间都是进行全量数据同步,但是从redis 2.8开始,即使主从连接中途断掉,也不需要进行全量同步,因为从这个版本开始融入了部分同步的概念。部分同步的实现依赖于在master服务器内存中给每个slave服务器维护了一份同步日志和同步标识,每个slave服务器在跟master服务器进行同步时都会携带自己的同步标识和上次同步的最后位置。当主从连接断掉之后,slave服务器隔断时间(默认1s)主动尝试和master服务器进行连接,如果从服务器携带的偏移量标识还在master服务器上的同步备份日志中,那么就从slave发送的偏移量开始继续上次的同步操作,如果slave发送的偏移量已经不再master的同步备份日志中(可能由于主从之间断掉的时间比较长或者在断掉的短暂时间内master服务器接收到大量的写操作),则必须进行一次全量更新。在部分同步过程中,master会将本地记录的同步备份日志中记录的指令依次发送给slave服务器从而达到数据一致。
redis集群
解释
每一个蓝色的圈都代表着一个redis的服务器节点,任何两个节点之间都是相互连通的,客户端可以与任何一个节点相连接,然后就可以访问集群中的任何一个节点。对其进行存取和其他操作。
Redis集群数据分片
每一个节点上都有两个东西:
- 插槽(slot)
集群创建的时候,需要给集群的节点分配插槽范围:0~16383; - cluster
个人把这个cluster理解为是一个集群管理的插件;
在node1执行set a a (key:a value:a);crc16%16383 = 10000 然后跳转到对应的节点执行set a a;get 也是一样的逻辑;