redis的模型,redis为什么快?redis为什么是单线程的?多核心机器如何部署redis(单进程占用单核)?
-
redis是一种支持key-value的等多种数据结构的内存数据库(nosql)。redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。
-
在redis中,key就是byte[](string),redis的数据结构(value)支持String,List,Set,Hash,zset(有序集合)。
-
redis为什么快?
1)数据都是完全基于内存的
2)数据结构简单
3)使用多路I/O复用:多路I/O复用模型是利用 select、poll、epoll 可以同时监察多个流的 I/O 事件的能力,在空闲的时候,会把当前线程阻塞掉,当有一个或多个流有 I/O 事件时,就从阻塞态中唤醒,于是程序就会轮询一遍所有的流(epoll 是只轮询那些真正发出了事件的流),并且只依次顺序的处理就绪的流,这种做法就避免了大量的无用操作。这里“多路”指的是多个网络连接,“复用”指的是复用同一个线程。采用多路 I/O 复用技术可以让单个线程高效的处理多个连接请求(尽量减少网络 IO 的时间消耗),且 Redis 在内存中操作数据的速度非常快,也就是说内存内的操作不会成为影响Redis性能的瓶颈,主要由以上几点造就了 Redis 具有很高的吞吐量。
4)单线程:避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗
5)使用底层模型不同,它们之间底层实现方式以及与客户端之间通信的应用协议不一样,Redis直接自己构建了VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求。 -
redis为什么是单线程的?
因为Redis是基于内存的操作,CPU不是Redis的瓶颈,Redis的瓶颈最有可能是机器内存的大小或者网络带宽。既然单线程容易实现,而且CPU不会成为瓶颈,那就顺理成章地采用单线程的方案了。 -
多核心机器如何部署redis(单进程占用单核)?
在单机开多个Redis 实例。Redis是用"单线程-多路复用io模型"来实现高性能的内存数据服务的,这种机制避免了使用锁,但是同时这种机制在进行sunion之类的比 较耗时的命令时会使redis的并发下降。因为是单一线程,所以同一时刻只有一个操作在进行,所以,耗时的命令会导致并发的下降,不只是读并发,写并发也 会下降。而单一线程也只能用到一个cpu核心,所以可以在同一个多核的服务器中,可以启动多个实例,组成master-master或者master- slave的形式,耗时的读命令可以完全在slave进行。
epoll,poll和select;
-
时间复杂度
(1)select==>时间复杂度O(n)
它仅仅知道了,有I/O事件发生了,却并不知道是哪那几个流(可能有一个,多个,甚至全部),我们只能无差别轮询所有流,找出能读出数据,或者写入数据的流,对他们进行操作。所以select具有O(n)的无差别轮询复杂度,同时处理的流越多,无差别轮询时间就越长。
(2)poll==>时间复杂度O(n)
poll本质上和select没有区别,它将用户传入的数组拷贝到内核空间,然后查询每个fd对应的设备状态, 但是它没有最大连接数的限制,原因是它是基于链表来存储的.
(3)epoll==>时间复杂度O(1)
epoll可以理解为event poll,不同于忙轮询和无差别轮询,epoll会把哪个流发生了怎样的I/O事件通知我们。所以我们说epoll实际上是事件驱动(每个事件关联上fd)的,此时我们对这些流的操作都是有意义的。(复杂度降低到了O(1)) -
select,poll,epoll本质上都是同步I/O,因为他们都需要在读写事件就绪后自己负责进行读写,也就是说这个读写过程是阻塞的,而异步I/O则无需自己负责进行读写,异步I/O的实现会负责把数据从内核拷贝到用户空间。
-
select、poll、epoll 区别总结:
1、支持一个进程所能打开的最大连接数
select:单个进程所能打开的最大连接数有FD_SETSIZE宏定义,其大小是32个整数的大小(在32位的机器上,大小就是3232,同理64位机器上FD_SETSIZE为3264),当然我们可以对进行修改,然后重新编译内核,但是性能可能会受到影响,这需要进一步的测试。
poll:poll本质上和select没有区别,但是它没有最大连接数的限制,原因是它是基于链表来存储的
epoll:虽然连接数有上限,但是很大,1G内存的机器上可以打开10万左右的连接,2G内存的机器可以打开20万左右的连接
2、FD剧增后带来的IO效率问题
select:因为每次调用时都会对连接进行线性遍历,所以随着FD的增加会造成遍历速度慢的“线性下降性能问题”。
poll:同上
epoll:因为epoll内核中实现是根据每个fd上的callback函数来实现的,只有活跃的socket才会主动调用callback,所以在活跃socket较少的情况下,使用epoll没有前面两者的线性下降的性能问题,但是所有socket都很活跃的情况下,可能会有性能问题。
3、 消息传递方式
select:内核需要将消息传递到用户空间,都需要内核拷贝动作
poll:同上
epoll:epoll通过内核和用户空间共享一块内存来实现的。
redis,mysql操作的时间数量级;
mySQL里有2000w数据,redis中只存20w的数据,如何保证redis中的数据都是热点数据?
redis 内存数据集大小上升到一定大小的时候,就会施行数据淘汰策略。
redis 提供 6种数据淘汰策略:
voltile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰
volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰
volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰
allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰
allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
no-enviction(驱逐):禁止驱逐数据
redis各种集群的方式,哨兵模式;
- 集群模式和哨兵模式的区别
1.哨兵模式监控权交给了哨兵系统,集群模式中是工作节点自己做监控
2.哨兵模式发起选举是选举一个leader哨兵节点来处理故障转移,集群模式是在从节点中选举一个新的主节点,来处理故障的转移
https://www.cnblogs.com/runnerjack/p/10269277.html
redis持久化的方式,aof文件太大了怎么办,主从同步的方式;
redis持久化的方式
- RDB(快照)持久化和AOF(仅附加文件)持久化。
- RDB:将存储在内存的数据以快照的方式写入二进制文件中,如默认dump.rdb中。
- 使用AOF持久时,服务会将每个收到的写命令通过写函数追加到文件中(appendonly.aof)
aof文件太大了怎么办
执行BGREWRITEAOF命令对redis的AOF进行重写。
文件能缩小的原因是:
1.旧文件中的无效命令不会保留,如del key1,sort。
2.多条合并成一条,如lplush list a,lplush list b转换为lplush a b,也可以合并重复项。
主从同步的方式
Redis主从复制
1.Master可以拥有多个slave
2.多个slave可以连接同一个Master外,还可以连接到其他的slave
3.主从复制不会阻塞Master,在主从复制时,Master可以处理client请求。
4.提供系统的伸缩性。
**
redis的五种常用数据结构,以及对应的底层数据结构的实现(zpilist,skiplist,quicklist,sds等等要有些了解);
**
- https://blog.csdn.net/Future_LL/article/details/88525004