目录
-
- 前言
- Redis基础
-
- 项目有用到redis吗?你们项目为什么用redis?
- redis为什么这么快?
- 了解Redis的线程模型吗?
- Redis优缺点?
- redis如何实现持久化?
- RDB持久化过程?
- AOF持久化过程?AOF持久化会出现阻塞吗?为什么?
- 你知道AOF重写吗?为什么要进行重写?简单说下AOF重写流程?
- RDB和AOF有什么区别?分别在什么场景下使用RDB和AOF?
- RDB,AOF都开启时,服务器是如何加载数据的,数据以谁为准?
- Redis什么情况下会出现阻塞,怎么解决?
- 知道哪些redis命令?平时用的最多的命令是什么?
- 如何处理redis过期键?你知道哪些删除策略?分别有什么优缺点?
- redis最大支持多少客户端连接?连接数满了怎么办?
- redis有内存限制吗?内存大小如何设置?内存被占满如何处理?
- 说说内存淘汰机制?有哪些策略?
- redis数据结构
- redis多机与分布式
- redis综合实战问题
前言
放弃幻想,拒绝大饼,准备战斗!!!
所有内容均为自用整理收集,答案仅供参考,如有不同意见欢迎评论区私信交流。
Redis基础
项目有用到redis吗?你们项目为什么用redis?
根据实际项目来谈,比如用于(分布式)会话管理、(分布式)缓存、轻量级消息队列、计数器、限流、排序、消息代理、分布式锁、以及点赞排行榜等实时业务等。
为什么用:速度快,高性能、高并发、丰富的数据结构支持、分布式可扩展性高。
redis为什么这么快?
- 内存:redis的所有数据都在内存中,因此不需要访问磁盘,极大的降低了访问延迟;内存操作(读写)性能高,支持每秒百万级操作。
- 单线程:redis以单线程模式运行,避免了多线程上下文切换的开销问题和多线程竞争问题,提高了CPU利用效率。
- 高效的数据结构:redis利用了几个高效的底层数据结构来提高数据操作效率。
- 非阻塞I/O多路复用机制:Redis使用非阻塞I/O,这种机制使得redis可以处理多个连接而不阻塞其他操作,从而能快速处理请求,实现高并发和高吞吐量。
了解Redis的线程模型吗?
Reactor模型?
Redis基于Reactor模式开发网络事件处理器,redis将此称为文件事件处理器(file event handler),该处理器以单线程模式运行和处理事件。
文件事件处理器分为四个部分:
- 套接字
- I/O多路复用程序:用来监听多个套接字请求。
- 文件事件分派器:将套接字的事件交给不同的事件处理器。
- 具体的事件处理器:实现不同的网络通信需求,比如应答客户端连接、接收客户端命令请求、返回执行结果等操作。
一个文件事件实际上就是套接字操作的抽象,当一个套接字准备好执行连接应答(accept)、写入、读取、关闭操作时就会产生一个文件事件。redis服务器通常会产生多个套接字(多个客户端多个连接访问),所以文件事件有可能会并发的出现,这时I/O多路复用程序会将所有事件的套接字放在一个队列里,然后文件事件分派器根据该队列有序、同步的接收套接字,由于文件事件处理是以单线程运行,所有只有在上一个套接字生产的事件执行完毕后,才会执行下一个套接字事件。
Redis优缺点?
优点:高性能、高并发
- 高性能:redis将数据存储在内存中,因此读写速度非常快。
- 高并发:redis基于Reactor 模式开发的网络事件处理器(文件事件处理器)是单线程模式运行的,所有操作都是原子性的,天然就支持高并发。
- 数据结构丰富:redis支持各种抽象数据结构,如字符串,列表,映射,集合,排序集合,HyperLogLogs,位图,流和空间索引。
- 支持持久化:redis支持将数据持久化到磁盘,提供可靠的数据保证。
- 分布式支持:redis支持主从复制和哨兵机制,可以实现数据备份、读写分离和自动故障转移,提高系统的可用性和可靠性。
缺点(内存消耗、数据一致性问题、阻塞):
- 内存消耗较大:由于redis将数据存储在内存中,因此对于大规模数据的存储需求,需要考虑服务器的内存容量和成本。
- CPU操作瓶颈:单线程模型可以避免上下文切换,但是也无法利用现代多核处理器的性能,对于CPU密集型的操作或服务器存在CPU密集型服务时可能存在性能瓶颈(一般很少见,redis的瓶颈主要在内存和网络),这种情况下就不适合处理大量并发请求。
- 线程阻塞:当单线程执行的命令阻塞时(慢查询、大key操作、网络问题等),将严重影响redis的性能。
- 数据一致性:当redis作为缓存使用时,就一定存在缓存和数据库数据不一致的问题。此外redis的主从复制存在一定的延迟。
- 无法处理复杂查询:redis不支持复杂查询操作,对于需要进行复杂数据分析和统计的场景不太适用。
- 数据容量受限:由于redis将数据存储在内存中,所以数据的容量受到内存大小的限制,无法存储超过内存容量的数据。
redis如何实现持久化?
为什么要持久化?redis是内存数据库,它的数据都存储在内存中,如果不把数据保存到磁盘里,那么服务器进程一旦退出,服务器的数据就丢失了。
通过两种方式:
- RDB(Persistence DB):RDB类似快照,它只能持久化某一时刻的服务器数据。RDB持久化后,文件将被保存至同文件夹下的
dump.rdb
文件中,且以压缩的二进制文件表示,服务器重启都会加载该文件以加载数据。 - AOF(Append Only File):AOF可以支持实时的数据持久化。AOF持久化功能通过保存redis服务器所执行的写命令来记录数据库状态,默认存储在
appendonly.aof
中,AOF文件中存储的都是redis相关命令。
RDB持久化过程?
1. 持久化部分:
Redis有俩个命令进行RDB持久化:
- SAVE:将会阻塞redis进程,此时服务器不能处理任何命令请求,直到RDB文件创建完毕。
- BGSAVE:派生子进程(创建子进程执行fork函数时服务器也将会阻塞,不过用时会很短),由子进程创建RDB,服务器进程继续
bgsave命令持久化过程如下:
- fork:创建子线程
- rdbSave:子线程创建rdb文件(save命令相当于是父进程直接执行这个函数)
- signal_parent:子线程创建完成后向父进程发送信号
RDB持久化可以手动执行,也可以根据服务器配置选项定期执行,在配置文件中设置save属性,会让服务器每隔一段时间自行执行一次bgsave命令。可以配置多个save选项,任一选项条件满足时都被会执行。
# save <second> <修改次数>
save 900 1
save 300 10
save 60 10000
# bgsave保存出错时,停止继续写入
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
# The filename where to dump the DB
dbfilename dump.rdb
2. 载入数据:
服务器启动时启动的,检测到RDB文件就会自动载入RDB中的数据。
AOF持久化过程?AOF持久化会出现阻塞吗?为什么?
1. 持久化部分:
AOF持久化功能的实现可以分为命令追加、文件写入和同步。
- 命令追加:当服务器完成一个写命令之后,并不会直接将这些命令写入AOF文件,而是以Redis协议格式将被执行的写命令追加到服务器缓冲区(aof_bug)的末尾。
- 文件写入与同步:根据设置的数据同步策略(always、everysec、no),当满足同步条件或缓冲区满时,redis会将AOF缓冲区中的数据一次性写入磁盘的AOF文件。
文件写入的配置如下:
# appendfsync always
# appendfsync no
appendfsync everysec
写入类型的区别:
- always:每次执行写命令都将缓冲区的内容写入AOF文件。效率最慢,也最安全,故障停机只会丢失一个事件循环中的数据命令。
- everysec:如果上次同步AOF文件时间距离现在已经超过了1秒,就进行文件同步。该同步由一个线程单独负责效率够快,且故障停机也只会丢失一秒钟的命令数据。
- no:由操作系统决定何时进行AOF文件的同步。一般来说,os可能会等到缓冲区的空间被填满、或者超过了指定时限之后,才真正地将缓冲区的数据写入到磁盘里面。fsync和fdatasync两个同步函数,可以强制让os立即将缓冲区中的数据写入到磁盘里面。总体写入AOF文件的速度最快,但是单次同步时长是三种模式中最长的。
2. 载入数据:
AOF文件只包含了重建数据库状态所需的所有命令,因此服务器只需要重新执行一遍AOF文件中保存的写命令即可恢复服务器状态。大致步骤如下:
- 创建一个不带网络连接的伪客户端,用来模拟客户端发送写命令。
- 从AOF文件中执行并分析出一条写命令
- 使用伪客户端执行被读出的写命令。
- 重复读取和写入,直到AOF文件被处理完毕。
3. AOF持久化会出现阻塞:
Redis每次执行写命令都将缓冲区的内容写入AOF文件,此时线程可能会因为持久化操作(磁盘IO)而阻塞。
你知道AOF重写吗?为什么要进行重写?简单说下AOF重写流程?
由于AO是F通过保存被执行的写命令来记录数据库状态,随时间流失,AOF文件中的内容会越来越多,体积越来越大,且会包含很多无用数据,比如新增键后又删除改键,AOF总是会保存这两个操作,实际上该键被删除已经不需要记录了,这种些命令显然没有存在的必要。
因此,为了解决