Redis八股文
1.Redis是什么?
Redis 是一个基于 C 语言开发的开源数据库(BSD 许可),与传统数据库不同的是 Redis 的数据是存在内存中的(内存数据库),读写速度非常快,被广泛应用于缓存方向。并且,Redis 存储的是 KV 键值对数据。
2.Redis的优缺点
Redis是一个开源的、内存存储、支持键值对、具有持久性的数据结构存储系统,具有以下优缺点:
优点:
- 高性能:Redis将数据全部存储在内存中,并使用单线程模型,这使得Redis的读写速度非常快。
- 丰富的数据结构:Redis支持多种数据结构,包括字符串、列表、哈希表、集合和有序集合等,这些数据结构可以满足不同应用场景的需求。
- 数据持久化:Redis支持将数据持久化到磁盘中,包括快照和日志文件两种方式,这使得Redis可以在系统宕机后快速恢复数据。
- 支持分布式:Redis支持分布式架构,可以将数据分散到多个节点中,提高系统的可扩展性和容错性。
- 简单易用:Redis提供了简单易用的命令行接口,同时也支持多种编程语言的客户端,使用起来非常方便。
缺点:
- 数据存储受限:由于Redis将所有数据存储在内存中,所以受到内存容量的限制,如果数据量很大,需要更多的内存。
- 单线程模型:虽然Redis使用单线程模型来保证读写性能,但是在高并发情况下,单线程模型也可能成为瓶颈。
- 不适合存储大文件:由于Redis是将所有数据存储在内存中,因此不适合存储大文件等大型二进制数据。
- 数据一致性:Redis支持数据持久化,但是在高并发的情况下,可能会存在数据一致性问题,需要进行额外的配置和处理。
- 配置复杂:Redis提供了多种配置选项,需要根据不同的使用场景进行不同的配置,这可能会增加系统配置的复杂度。
3.Redis为什么这么快
- 基于内存:Redis 将数据全部存储在内存中,而内存的访问速度是磁盘的上千倍,这使得 Redis 能够快速地读取和写入数据。
- 高效的事件处理模型:Redis 基于 Reactor 模式设计开发了一套高效的事件处理模型,主要是单线程事件循环和 IO 多路复用,这使得 Redis 能够高效地处理大量的并发请求。
- 优化过的数据结构实现:Redis 内置了多种优化过后的数据结构实现,如哈希表、有序集合等,这些数据结构能够高效地处理常见的数据操作,如插入、删除、查找等。
- 异步非阻塞的网络模型:Redis 使用异步非阻塞的网络模型,这使得 Redis 能够高效地处理大量的并发请求,而不会因为等待 I/O 操作而阻塞线程,从而提高了系统的吞吐量。
- 数据持久化:Redis 支持将数据持久化到磁盘中,包括快照和日志文件两种方式,这使得 Redis 可以在系统宕机后快速恢复数据,从而提高了系统的可靠性。
4.Redis为何选择单线程
Redis 选择单线程模型的主要原因是为了避免线程切换带来的开销和竞争条件带来的复杂性,从而提高系统的性能和可靠性。具体来说,单线程模型带来以下几个优点:
- 避免线程切换带来的开销:线程切换会带来一定的开销,包括上下文切换和内存开销等,而单线程模型能够避免这些开销,从而提高系统的性能。
- 避免竞争条件带来的复杂性:在多线程模型下,多个线程之间会存在竞争条件,需要使用锁等机制来避免竞争条件带来的复杂性,而单线程模型能够避免这些复杂性,从而提高系统的可靠性。
- 更容易实现:单线程模型相对于多线程模型更容易实现和维护,因为它不需要考虑线程间的同步和通信等问题。
- 更容易进行优化:由于单线程模型不会存在多线程间的竞争条件,因此可以更容易地进行优化,如利用 CPU 缓存等。
需要注意的是,Redis 的单线程模型并不代表它只能处理一个请求,实际上 Redis 通过事件处理模型和异步非阻塞的网络模型,能够同时处理大量的并发请求,从而实现高吞吐量和低延迟。
5.Redis应用场景有哪些
Redis 作为一种高性能、可靠性高的内存数据库,在许多应用场景中得到了广泛的应用。以下是 Redis 的一些常见应用场景:
- 缓存:Redis 作为一种高速缓存数据库,可以将热点数据缓存在内存中,从而提高系统的读写性能。
- 消息队列:Redis 的发布/订阅模式和 List 数据结构可以实现轻量级的消息队列,从而支持异步消息通信。
- 计数器和排行榜:Redis 的原子性操作和 Sorted Set 数据结构可以实现高效的计数器和排行榜功能。
- 分布式锁:Redis 的原子性操作和过期时间可以实现高效的分布式锁功能,从而保证多个进程或线程之间的数据访问互斥。
- 会话存储:Redis 可以作为会话存储数据库,将用户的会话信息存储在内存中,从而支持高并发的 Web 应用程序。
- 地理位置和空间索引:Redis 的 Geo 数据结构可以实现高效的地理位置和空间索引功能,从而支持 LBS 应用程序。
- 数据库持久化:Redis 支持将数据持久化到磁盘中,从而支持数据备份和恢复,提高系统的可靠性。
综上所述,Redis 在缓存、消息队列、计数器和排行榜、分布式锁、会话存储、地理位置和空间索引、数据库持久化等多个应用场景中都具有很好的表现。
6.Memcached和Redis的区别
- Redis 支持更丰富的数据类型(支持更复杂的应用场景)。Redis 不仅仅支持简单的 k/v 类型的数据,同时还提供 list,set,zset,hash 等数据结构的存储。Memcached 只支持最简单的 k/v 数据类型。
- Redis 支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用,而 Memcached 把数据全部存在内存之中。
- Redis 有灾难恢复机制。 因为可以把缓存中的数据持久化到磁盘上。
- Redis 在服务器内存使用完之后,可以将不用的数据放到磁盘上。但是,Memcached 在服务器内存使用完之后,就会直接报异常。
- Memcached 没有原生的集群模式,需要依靠客户端来实现往集群中分片写入数据;但是 Redis 目前是原生支持 cluster 模式的。
- Memcached 是多线程,非阻塞 IO 复用的网络模型;Redis 使用单线程的多路 IO 复用模型。 (Redis 6.0 引入了多线程 IO )
- Redis 支持发布订阅模型、Lua 脚本、事务等功能,而 Memcached 不支持。并且,Redis 支持更多的编程语言。
- Memcached 过期数据的删除策略只用了惰性删除,而 Redis 同时使用了惰性删除与定期删除。
7.Redis 数据类型有哪些
- 5 种基础数据结构 :String(字符串)、List(列表)、Set(集合)、Hash(散列)、Zset(有序集合)。
- 3 种特殊数据结构 :HyperLogLogs(基数统计)、Bitmap (位存储)、Geospatial (地理位置)
8.keys命令存在的问题
- 性能问题:keys 命令会遍历整个 Redis 数据库中的所有键值,对于大型 Redis 数据库来说,这个操作可能会耗费大量时间和系统资源,导致 Redis 服务器的性能下降。
- 阻塞问题:由于 keys 命令会遍历整个 Redis 数据库,因此在执行 keys 命令期间,Redis 服务器会被阻塞,无法响应其他请求。
- 安全问题:keys 命令可以返回 Redis 数据库中的所有键值,包括一些敏感数据,如果在生产环境中误用 keys 命令,可能会导致泄露敏感数据。
9.SortedSet和List异同点
相同点:
- 都可以存储多个元素。
- 都可以通过索引来访问元素。
- 都可以在头部或尾部插入和删除元素。
- 都可以进行范围查询,即查询某个范围内的元素。
- 都支持阻塞式的弹出和插入操作。
- 都可以通过多种命令实现数据结构的基本操作,如增删改查。
不同点:
- 数据结构不同:List 是链表结构,SortedSet 是平衡树结构。
- 元素的唯一性:List 允许存储重复的元素,而 SortedSet 不允许存储重复的元素,并且元素按照指定的权重进行排序。
- 排序方式不同:List 中的元素按照插入顺序排序,而 SortedSet 中的元素按照指定的权重排序。
- 操作复杂度不同:List 中的大多数操作的复杂度都是 O(1) 级别的,而 SortedSet 中的大多数操作的复杂度都是 O(log N) 级别的,其中 N 表示元素个数。
- 适用场景不同:List 适用于先进先出(FIFO)的场景,如消息队列、任务队列等;SortedSet 适用于有序排列并且需要去重的场景,如排行榜、计数器等。
10.Redis事务
Redis 事务的基本使用方法如下:
- 通过 MULTI 命令开启一个事务。
- 在事务中执行多个命令,这些命令并不会立即被执行,而是被放入一个队列中。
- 通过 EXEC 命令将事务中的所有命令依次执行。
- 如果在事务执行过程中发生错误,可以通过 DISCARD 命令取消事务。
下面是一个简单的 Redis 事务示例:
sqlCopy code
MULTI SET key1 value1 SET key2 value2 GET key1 EXEC
在这个示例中,首先通过 MULTI 命令开启一个事务,然后执行了三个命令:SET key1 value1、SET key2 value2 和 GET key1。这些命令并不会立即被执行,而是被放入一个队列中。最后通过 EXEC 命令将事务中的所有命令依次执行,如果所有命令都执行成功,则返回结果集;否则返回 nil。
Redis 事务还支持一些高级功能,如 WATCH 命令、CAS 命令等,可以用来实现乐观锁、原子操作等功能。
需要注意的是,在 Redis 中事务并不是严格意义上的 ACID 事务,因为 Redis 事务并不能保证所有命令的原子性,即使其中一个命令执行失败也不会回滚已执行的命令。因此,在使用 Redis 事务时需要格外小心,避免出现意外情况。
11.持久化机制
RDB方式
Redis 可以通过创建快照来获得存储在内存里面的数据在某个时间点上的副本。Redis 创建快照之后,可以对快照进行备份,可以将快照复制到其他服务器从而创建具有相同数据的服务器副本(Redis 主从结构,主要用来提高 Redis 性能),还可以将快照留在原地以便重启服务器的时候使用。
快照持久化是 Redis 默认采用的持久化方式,在 redis.conf 配置文件中默认有此下配置:
save 900 1 #在900秒(15分钟)之后,如果至少有1个key发生变化,Redis就会自动触发bgsave命令创建快照。save 300 10 #在300秒(5分钟)之后,如果至少有10个key发生变化,Redis就会自动触发bgsave命令创建快照。save 60 10000 #在60秒(1分钟)之后,如果至少有10000个key发生变化,Redis就会自动触发bgsave命令创建快照。
Redis 提供了两个命令来生成 RDB 快照文件:
- save : 同步保存操作,会阻塞 Redis 主线程;
- bgsave : fork 出一个子进程,子进程执行,不会阻塞 Redis 主线程,默认选项。
AOF方式
与快照持久化相比,AOF 持久化的实时性更好,因此已成为主流的持久化方案。默认情况下 Redis 没有开启 AOF(append only file)方式的持久化,可以通过 appendonly 参数开启:
appendonly yes
开启 AOF 持久化后每执行一条会更改 Redis 中的数据的命令,Redis 就会将该命令写入到内存缓存 server.aof_buf 中,然后再根据 appendfsync 配置来决定何时将其同步到硬盘中的 AOF 文件。
AOF 文件的保存位置和 RDB 文件的位置相同,都是通过 dir 参数设置的,默认的文件名是 appendonly.aof。
在 Redis 的配置文件中存在三种不同的 AOF 持久化方式,它们分别是:
appendfsync always #每次有数据修改发生时都会写入AOF文件,这样会严重降低Redis的速度
appendfsync everysec #每秒钟同步一次,显式地将多个写命令同步到硬盘
appendfsync no #让操作系统决定何时进行同步
为了兼顾数据和写入性能,用户可以考虑 appendfsync everysec 选项 ,让 Redis 每秒同步一次 AOF 文件,Redis 性能几乎没受到任何影响。而且这样即使出现系统崩溃,用户最多只会丢失一秒之内产生的数据。当硬盘忙于执行写入操作的时候,Redis 还会优雅的放慢自己的速度以便适应硬盘的最大写入速度。
12.AOF 重写了解吗?
当 AOF 变得太大时,Redis 能够在后台自动重写 AOF 产生一个新的 AOF 文件,这个新的 AOF 文件和原有的 AOF 文件所保存的数据库状态一样,但体积更小。
AOF 重写是一个有歧义的名字,该功能是通过读取数据库中的键值对来实现的,程序无须对现有 AOF 文件进行任何读入、分析或者写入操作。
在执行 BGREWRITEAOF 命令时,Redis 服务器会维护一个 AOF 重写缓冲区,该缓冲区会在子进程创建新 AOF 文件期间,记录服务器执行的所有写命令。当子进程完成创建新 AOF 文件的工作之后,服务器会将重写缓冲区中的所有内容追加到新 AOF 文件的末尾,使得新的 AOF 文件保存的数据库状态与现有的数据库状态一致。最后,服务器用新的 AOF 文件替换旧的 AOF 文件,以此来完成 AOF 文件重写操作。
Redis 7.0 版本之前,如果在重写期间有写入命令,AOF 可能会使用大量内存,重写期间到达的所有写入命令都会写入磁盘两次。
13.RDB和AOF如何选择?
RDB 比 AOF 优秀的地方:
- RDB 文件存储的内容是经过压缩的二进制数据, 保存着某个时间点的数据集,文件很小,适合做数据的备份,灾难恢复。AOF 文件存储的是每一次写命令,类似于 MySQL 的 binlog 日志,通常会必 RDB 文件大很多。当 AOF 变得太大时,Redis 能够在后台自动重写 AOF。新的 AOF 文件和原有的 AOF 文件所保存的数据库状态一样,但体积更小。不过, Redis 7.0 版本之前,如果在重写期间有写入命令,AOF 可能会使用大量内存,重写期间到达的所有写入命令都会写入磁盘两次。
- 使用 RDB 文件恢复数据,直接解析还原数据即可,不需要一条一条地执行命令,速度非常快。而 AOF 则需要依次执行每个写命令,速度非常慢。也就是说,与 AOF 相比,恢复大数据集的时候,RDB 速度更快。
AOF 比 RDB 优秀的地方:
- RDB 的数据安全性不如 AOF,没有办法实时或者秒级持久化数据。生成 RDB 文件的过程是比较繁重的, 虽然 BGSAVE 子进程写入 RDB 文件的工作不会阻塞主线程,但会对机器的 CPU 资源和内存资源产生影响,严重的情况下甚至会直接把 Redis 服务干宕机。AOF 支持秒级数据丢失(取决 fsync 策略,如果是 everysec,最多丢失 1 秒的数据),仅仅是追加命令到 AOF 文件,操作轻量。
- RDB 文件是以特定的二进制格式保存的,并且在 Redis 版本演进中有多个版本的 RDB,所以存在老版本的 Redis 服务不兼容新版本的 RDB 格式的问题。
- AOF 以一种易于理解和解析的格式包含所有操作的日志。你可以轻松地导出 AOF 文件进行分析,你也可以直接操作 AOF 文件来解决一些问题。比如,如果执行FLUSHALL命令意外地刷新了所有内容后,只要 AOF 文件没有被重写,删除最新命令并重启即可恢复之前的状态。
14.Redis常见的部署方式有哪些
- 单机部署
单机部署是指将Redis部署在单个服务器上,通过监听特定端口提供服务。这种方式简单易用,适用于小规模应用场景,但是容易出现单点故障,无法满足高可用性要求。
- 主从复制部署
主从复制部署是指在主节点上写入数据,在从节点上进行复制。通过多个从节点来实现读写分离,提高读取性能,并且从节点可以作为主节点的备份,保证高可用性。
- 集群部署
集群部署是将Redis实例分布在多个物理节点上,通过集群管理器对实例进行管理和调度,实现高可用性和横向扩展。集群部署相对于主从复制部署,能够提供更高的性能和更好的可扩展性,但是需要考虑数据分片和节点之间的网络通信问题。
- 哨兵部署
哨兵部署是在主从复制基础上增加了哨兵节点来监控主节点状态,当主节点宕机时,哨兵节点会自动切换从节点为新的主节点。哨兵部署可以提供较高的可用性,并且相对于集群部署来说,管理和维护成本更低,但是对于大规模数据和高并发场景来说,性能和可扩展性不如集群部署。
15.主从复制
Redis主从复制是一种数据同步机制,其中一个Redis实例作为主节点(Master),而其他Redis实例则作为从节点(Slave)来复制主节点的数据。
主节点接收客户端的写操作,并将这些写操作的结果通过网络发送给从节点,从节点接收这些结果并更新本地数据。这样,即使主节点宕机,从节点也可以继续提供服务并保持数据的完整性。
在配置Redis主从复制时,需要指定主节点的IP地址和端口号,并将从节点的配置文件中的slaveof选项设置为主节点的IP地址和端口号。一旦从节点成功连接到主节点,它将开始接收主节点的数据,并将其存储在本地内存中。
主从复制可以用于多种场景,例如:
- 数据备份:从节点可以用作主节点数据的备份,以避免数据丢失。
- 负载均衡:从节点可以用于分担主节点的负载,提高系统的性能和稳定性。
- 读写分离:主节点可以专注于处理写操作,而从节点可以处理读操作,以提高系统的并发性能。
需要注意的是,主从复制并不是高可用性的解决方案,因为当主节点宕机时,需要手动切换从节点成为主节点来维护服务的可用性。如果需要高可用性,可以使用Redis Sentinel或Redis Cluster。
16.哨兵Sentinel
https://pdai.tech/md/db/nosql-redis/db-redis-x-sentinel.html
https://juejin.cn/post/6998564627525140494#heading-13
作用
- 监控:监控所有 Redis 节点的状态。
- 故障转移:当哨兵发现主节点下线时,会在所有从节点中选择一个作为新的主节点,并将所有其他节点的 Master 指向新的主节点。同时已下线的原主节点也会被降级为从节点,并修改配置将 Master 指向新的主节点,等到它重新上线时就会自动以从节点进行工作。
- 通知:当哨兵选举了新的主节点之后,可以通过 API 向客户端进行通知。
哨兵的原理
从库发现
对于哨兵的配置,我们只需要配置主库的信息,哨兵在连接主库之后,会调用 INFO 命令获取主库的信息,再从中解析出连接主库的从库信息,再以此和其他从库建立连接进行监控。
发布/订阅机制
哨兵们在连接同一个主库之后,是通过发布/订阅(pub/sub)模式来发现彼此的存在的。
监控
哨兵在对 Redis 节点建立 TCP 连接之后,会周期性地发送 PING 命令给节点(默认是 1s),以此判断节点是否正常。如果在 down-after-millisenconds 时间内没有收到节点的响应,它就认为这个节点掉线了。
主观下线
当哨兵发现与自己连接的其他节点断开连接,它就会将该节点标记为主观下线(+sdown),包括主节点、从节点或者其他哨兵都可以标记为 sdown 状态。
客观下线
哨兵确认主节点是否真的宕机这一步成为客观下线确认,如果主节点真的宕机了,哨兵就会将主节点标记为客观下线(+odown)状态。
客观下线投票过程
- 当哨兵发现主节点下线,标记主节点为 sdown 状态。
- 哨兵向其他哨兵发送 SENTINEL is-master-down-by-addr 命令,询问其他哨兵该主节点是否已下线。
- 其他哨兵在收到投票请求之后,会检查本地主缓存中主节点的状态并进行回复(1 表示下线,0 表示正常)。
- 发起的询问的哨兵在接收到回复之后,会累加“下线”的得票数。
- 当下线的票数大于一半哨兵数量并且不小于 quorum 时,就会将主节点标记为 odown 状态。并开始准备故障转移
- 发起投票的哨兵有一个投票倒计时,倒计时结束如果票数仍然不够的话,则放弃本次客观线下投票。并尝试继续与主节点建立连接。
17.Redis cluster
Redis Cluster 是 Redis 的分布式实现,允许您将 Redis 在多个节点之间水平扩展,提供高可用性和自动数据分片。Redis Cluster 自动将数据分配到多个节点上,这有助于分配负载并增加应用程序的吞吐量。
Redis Cluster 使用一种称为哈希槽的分片算法,它允许将每个键分配给集群中的特定节点。这确保每个节点仅存储数据的一个子集,从而更容易扩展和管理 Redis 数据库。
Redis Cluster 支持主从复制模型,其中每个主节点有一个或多个从节点。主节点负责处理读写操作,而从节点复制主节点的数据并作为热备份,在主节点故障时可以立即接替主节点的功能。
Redis Cluster 还提供自动故障转移,当主节点失败时,将自动替换为其中一个从节点。这有助于确保高可用性并在节点故障时防止数据丢失。
18.哈希分区算法有哪些
- CRC16算法:Redis cluster默认的哈希分区算法是CRC16算法,它是一种快速的哈希算法,具有良好的分布性和低碰撞率。在Redis cluster中,每个键都会被CRC16算法映射到一个16位整数上,然后根据这个整数对节点数取模得到该键所在的节点。
- CRC32算法:Redis cluster也支持CRC32算法作为哈希分区算法,它是一种更为复杂的哈希算法,具有更好的随机性和更低的碰撞率。在Redis cluster中,使用CRC32算法需要手动设置。
- MD5算法:Redis cluster还支持MD5算法作为哈希分区算法,它是一种更为安全的哈希算法,具有很高的随机性和很低的碰撞率。在Redis cluster中,使用MD5算法需要手动设置。
不同的哈希分区算法适用于不同的场景,CRC16算法在性能和效果上都有良好的表现,因此是Redis cluster默认的哈希分区算法。如果需要更高的哈希分布性和更低的碰撞率,可以考虑使用CRC32算法或MD5算法。
19.过期键的删除策略
常用的过期数据的删除策略就两个(重要!自己造缓存轮子的时候需要格外考虑的东西):
- 惰性删除 :只会在取出 key 的时候才对数据进行过期检查。这样对 CPU 最友好,但是可能会造成太多过期 key 没有被删除。
- 定期删除 : 每隔一段时间抽取一批 key 执行删除过期 key 操作。并且,Redis 底层会通过限制删除操作执行的时长和频率来减少删除操作对 CPU 时间的影响。
定期删除对内存更加友好,惰性删除对 CPU 更加友好。两者各有千秋,所以 Redis 采用的是 定期删除+惰性/懒汉式删除。但是,仅仅通过给 key 设置过期时间还是有问题的。因为还是可能存在定期删除和惰性删除漏掉了很多过期 key 的情况。这样就导致大量过期 key 堆积在内存里,然后就 Out of memory 了。
怎么解决这个问题呢?答案就是:Redis 内存淘汰机制。
20.内存淘汰策略有哪些
Redis 提供 6 种数据淘汰策略:
- volatile-lru(least recently used):从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰
- volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰
- volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰
- allkeys-lru(least recently used):当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的 key(这个是最常用的)
- allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
- no-eviction:禁止驱逐数据,也就是说当内存不足以容纳新写入数据时,新写入操作会报错。这个应该没人使用吧!
4.0 版本后增加以下两种:
- volatile-lfu(least frequently used):从已设置过期时间的数据集(server.db[i].expires)中挑选最不经常使用的数据淘汰
- allkeys-lfu(least frequently used):当内存不足以容纳新写入数据时,在键空间中,移除最不经常使用的 key。
21.如何保证缓存与数据库双写时的数据一致性
https://juejin.cn/post/6850418121754050567#comment
22.缓存穿透
缓存穿透说简单点就是大量请求的 key 是不合理的,根本不存在于缓存中,也不存在于数据库中 。这就导致这些请求直接到了数据库上,根本没有经过缓存这一层,对数据库造成了巨大的压力,可能直接就被这么多请求弄宕机了。
解决办法
最基本的就是首先做好参数校验,一些不合法的参数请求直接抛出异常信息返回给客户端。比如查询的数据库 id 不能小于 0、传入的邮箱格式不对的时候直接返回错误消息给客户端等等。
23.缓存雪崩
缓存在同一时间大面积的失效,导致大量的请求都直接落到了数据库上,对数据库造成了巨大的压力。 这就好比雪崩一样,摧枯拉朽之势,数据库的压力可想而知,可能直接就被这么多请求弄宕机了。
针对 Redis 服务不可用的情况:
- 采用 Redis 集群,避免单机出现问题整个缓存服务都没办法使用。
- 限流,避免同时处理大量的请求。
针对热点缓存失效的情况:
- 设置不同的失效时间比如随机设置缓存的失效时间。
- 缓存永不失效(不太推荐,实用性太差)。
- 设置二级缓存。
缓存雪崩和缓存击穿有什么区别?
缓存雪崩和缓存击穿比较像,但缓存雪崩导致的原因是缓存中的大量或者所有数据失效,缓存击穿导致的原因主要是某个热点数据不存在与缓存中(通常是因为缓存中的那份数据已经过期)
24.缓存击穿
缓存击穿中,请求的 key 对应的是 热点数据 ,该数据 存在于数据库中,但不存在于缓存中(通常是因为缓存中的那份数据已经过期) 。这就可能会导致瞬时大量的请求直接打到了数据库上,对数据库造成了巨大的压力,可能直接就被这么多请求弄宕机了。
有哪些解决办法?
- 设置热点数据永不过期或者过期时间比较长。
- 针对热点数据提前预热,将其存入缓存中并设置合理的过期时间比如秒杀场景下的数据在秒杀结束之前不过期。
- 请求数据库写数据到缓存之前,先获取互斥锁,保证只有一个请求会落到数据库上,减少数据库的压力。
缓存穿透和缓存击穿有什么区别?
缓存穿透中,请求的 key 既不存在于缓存中,也不存在于数据库中。
缓存击穿中,请求的 key 对应的是 热点数据 ,该数据 存在于数据库中,但不存在于缓存中(通常是因为缓存中的那份数据已经过期)
25.Redis 怎么实现消息队列?
(1)List 结构;(2)Pub/Sub 模式;(3)Stream 结构
https://mp.weixin.qq.com/s/_q0bI62iFrG8h-gZ-bCvNQ
26.pipeline的作用
Redis Pipeline是一种优化Redis批量查询的技术。它允许客户端将多个Redis命令一次性发送给Redis服务器,而不需要等待每个命令的响应。这样可以减少客户端与服务器之间的往返通信,从而提高Redis的性能。
具体来说,Redis Pipeline的工作原理如下:
- 客户端将多个Redis命令打包成一个请求。
- 客户端将打包后的请求发送给Redis服务器。
- Redis服务器收到请求后,不立即执行,而是将请求缓存起来。
- Redis服务器按照请求的顺序逐一执行请求,并将执行结果保存在缓存中。
- 客户端最终一次性接收所有命令的执行结果。
相比于单独发送每个Redis命令,使用Pipeline可以极大地减少通信延迟和网络带宽,从而提高Redis的吞吐量。在一些需要批量查询Redis的场景下,使用Pipeline可以显著提高应用程序的性能。
27.LUA脚本
- 减少网络开销,在 Lua脚本 中可以把多个命令放在同一个脚本中运行
- 原子操作,Redis 会将整个脚本作为一个整体执行,中间不会被其他命令插入(编写脚本过程中无需担心会出现竞态条件)
- 复用性,客户端发送的脚本会永远存储在 Redis中,意味着其他客户端可以复用这一脚本。
28.什么时候使用pipeline,什么时候使用lua
- 当多个redis命令之间没有依赖、顺序关系(例如第二条命令依赖第一条命令的结果)时,建议使用pipline;
- 如果命令之间有依赖或顺序关系时,pipline就无法使用,此时可以考虑才用lua脚本的方式来使用。
28.什么是RedLock?
在RedLock中,多个客户端通过竞争获取一个分布式锁,只有获得锁的客户端才能够执行对共享资源的访问。为了防止分布式环境中出现单点故障,RedLock采用了多个Redis实例来存储锁信息,并且在获取锁时需要占用大多数Redis实例的锁才能成功获取锁,从而保证了分布式锁的可靠性和高可用性。
29.Redis单线程理解
RedLock是基于redis实现的分布式锁,它能够保证以下特性:
- 互斥性:在任何时候,只能有一个客户端能够持有锁;避免死锁:
- 当客户端拿到锁后,即使发生了网络分区或者客户端宕机,也不会发生死锁;(利用key的存活时间)
- 容错性:只要多数节点的redis实例正常运行,就能够对外提供服务,加锁或者释放锁;
RedLock算法思想,意思是不能只在一个redis实例上创建锁,应该是在多个redis实例上创建锁,n / 2 + 1,必须在大多数redis节点上都成功创建锁,才能算这个整体的RedLock加锁成功,避免说仅仅在一个redis实例上加锁而带来的问题。
30.lO多路复用
Redis 采用了多路复用机制,使其在网络 IO 操作中能并发处理大量的客户端请求,实现高吞吐率。
其实 Redis 是利用上Linux 中的 IO 多路复用机制, Linux 中的 IO 多路复用机制是指一个线程处理多个 IO 流。
简单来说,在 Redis 只运行单线程的情况下,该机制允许内核中,同时存在多个监听套接字和已连接套接字。
内核会一直监听这些套接字上的连接请求或数据请求。一旦有请求到达,就会交给 Redis 线程处理,这就实现了一个 Redis 线程处理多个 IO 流的效果。
相关文章:
Redis八股文
1.Redis是什么? Redis 是一个基于 C 语言开发的开源数据库(BSD 许可),与传统数据库不同的是 Redis 的数据是存在内存中的(内存数据库),读写速度非常快,被广泛应用于缓存方向。并且,…...
InnoDB——详细解释锁的应用,一致性读,自增长与外键
一致性非锁定读 一致性的非锁定读(consistent nonlocking read)是指InnoDB存储引擎通过行多版本控制的方式读取当前执行时数据库中行的数据。 如果读取的行正在执行 行Delete或Update操作,这时读取操作不会因此去等待行上锁的释放。相反&…...
C++模板基础(四)
函数模板(四) ● 函数模板的实例化控制 – 显式实例化定义: template void fun(int) / template void fun(int) //header.h template<typename T> void fun(T x) {std::cout << x << std::endl; }//main.cpp #include&quo…...
pycharm使用记录
文章目录下载安装后续其他设置编辑器设置关于debug下载安装 直接去pycharm官网下载社区版,这个版本本来就是免费的,而且功能其实已经够了 后续其他设置 首先,第一次启动时,记得在preference->interpreter中设置python环境&a…...
Linux命令·kill·killall
Linux中的kill命令用来终止指定的进程(terminate a process)的运行,是Linux下进程管理的常用命令。通常,终止一个前台进程可以使用CtrlC键,但是,对于一个后台进程就须用kill命令来终止,我们就需…...
Linux /proc/version 文件解析
/proc/version文件里面的内容: Linux version 4.14.180-perf (oe-user@oe-host) (clang version 10.0.5 for Android NDK, GNU ld (GNU Binutils) 2.29.1.20180115) #1 SMP PREEMPT Wed Mar 29 18:55:02 CST 2023 /proc/version文件里面记录了如下内容: 1、Linux kernel的…...
【Django 网页Web开发】15. 实战项目:管理员增删改查,md5密码和密码重置(08)(保姆级图文)
目录1. model编写数据表2. 管理员列表2.1 admin.py视图文件2.2 admin_list.html2.3 url.py2.4 最终效果3. 管理员添加3.0 md5包的书写3.1 form.py表单组件3.2 admin.py视图文件3.3 引入公共的添加数据html3.4 url.py3.5 最终效果4. 管理员编辑4.0 form表单组件4.1 admin.py视图…...
STL容器之<array>
文章目录测试环境array介绍头文件模块类定义对象构造初始化元素访问容器大小迭代器其他函数测试环境 系统:ubuntu 22.04.2 LTS 64位 gcc版本:11.3.0 编辑器:vsCode 1.76.2 array介绍 array是固定大小的序列式容器,它包含按严格…...
flask教程6:cookie和session
文章目录一、cookie1.1 什么是cookie?1.2 使用cookie1.2.1 设置cookie1.2.2设置cookie的有效期1.2.3在Flask中查询cookie1.2.4删除cookie二、session2.1实现session的两种思路2.1.1 第一种2.1.2 第二种2.2使用session2.2 .1设置session2.2.2 设置有效期2.2.3 获取se…...
【JavaEE初阶】第六节.网络原理TCP/IP协议
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言 一、TCP/IP协议五层协议栈; 1.1 应用层协议; 二、传输层协议; 2.1 UDP协议; 2.2 TCP协议; 2.…...
模式识别 —— 第六章 支持向量机(SVM)与核(Kernel)
模式识别 —— 第六章 支持向量机(SVM)与核(Kernel) 文章目录模式识别 —— 第六章 支持向量机(SVM)与核(Kernel)硬间隔(Hard-Margin)软间隔(Soft…...
总结 synchronized
目录synchronized的特性1. 互斥2. 刷新内存3. 可重入synchronized的使用1. 直接修饰普通方法2. 修饰静态方法3. 修饰代码块synchronized的锁机制基本特点关键锁策略 : 锁升级synchronized的特性 1. 互斥 synchronized 会起到互斥效果, 某个线程执行到某个对象的 synchronized…...
360周鸿祎又“开炮”:GPT 6-8就将产生自主意识!我们来测算一下对错
数据智能产业创新服务媒体——聚焦数智 改变商业近日,360的周鸿祎放言“GPT6到GPT8人工智能将会产生意识,变成新的物种。未来,人工智能大语言模型有可能实现自我进化,自动更新系统和自我升级,或者指数级进化能力&am…...
python——飞机大战小游戏
目录 1、导入模块 2、窗口操作 3、事件操作 4、长按事件 5、添加游戏背景 6、添加英雄飞机 7、获取飞机的图片矩形 8、基本游戏窗口 9、添加游戏窗口图片 10、英雄飞机登场 11、英雄飞机装备子弹并发射 1、enemy_plane 2、game_main 3、game_map 4、game_score …...
数组(完全二叉树)向下建堆法与堆排序O(N*logN)
TIPS AdjustUp & AdjustDown向上调整AdjustUp与向下调整AdjustDown的参数是一个数组(完全二叉树)需要进行调整操作的数值的下标/一个数组(完全二叉树)堆元素个数需要调整操作的数值的下标。实际上就是对完全二叉树当中的某一点…...
Lua require 函数使用
从 Lua 的用户文档中我们知道 require("modName") 函数是用来加载模块的,而如果这个modName已经用require 加载过的,再调用require时,将直接返回模块的值。因为函数首先查找 package.loaded 表, 检测 modName 是否被加载…...
【面试】如何定位线上问题?
这个面试题我在两年社招的时候遇到过,前几天面试也遇到了。我觉得我每一次都答得中规中矩,今天来梳理复盘下,下次又被问到的时候希望可以答得更好。 下一次我应该会按照这个思路去答: 1、如果线上出现了问题,我们更多…...
字节二面,原来我对自动化测试的理解太浅了
如果你入职一家新的公司,领导让你开展自动化测试,作为一个新人,你肯定会手忙脚乱,你会如何落地自动化测试呢? 01 什么是自动化 有很多人做了很长时间的自动化但却连自动化的概念都不清楚,这样的人也是很悲…...
Android11.0 应用升级成功后立即断电重启,版本恢复
问题:客户反馈内置的应用升级成功后立刻断电重启,应用的版本被恢复。 使用adb命令升级客户应用,查看版本显示已更新,/data/system目录下packages.xml和packages.xml中应用版本信息均已更新 C:\Users\dell>adb shell dumpsys …...
关于python常用软件用法:Pycharm 常用功能
人生苦短,我用python 一.Pycharm的基本使用 1.在Pycharm下为你的Python项目配置Python解释器 (1).Setting>Project Interpreter>源码资料电子书:点击此处跳转文末名片获取 二.在Pycharm下创建Python文件、Python模块 1.File>New&g…...
SOLIDWORKS你不知道的小技巧
◉ SOLIDWORKS圆弧长度标注点智能标注,再选中该圆弧,然后分别点圆弧的两个端点,点击左键可以标注圆弧长度。◉ SOLIDWORKS强力裁剪剪裁实体中的强劲剪裁,除了可以裁剪实体外,还可以任意延伸实体。◉ SOLIDWORKS转折线转…...
有了HTTP,为啥还要用RPC
既然有 HTTP 请求,为什么还要用 RPC 调用? 一直以来都没有深究过RPC和HTTP的区别,不都是写一个服务然后在客户端调用么? HTTP和RPC最本质的区别,就是 RPC 主要是基于 TCP/IP 协议的,而 HTTP 服务主要是基…...
[leetcode] 动态规划
背包 先啃懂 背包九讲 01背包,即物品有限。 for 物品for 容量(倒序)P1048 [NOIP2005 普及组] 采药 [ 原题 | 题解 ] P1049 [NOIP2001 普及组] 装箱问题 [ 原题 | 题解 ] P1507 NASA的食物计划 [ 原题 | 题解 ] P1510 精卫填海 [ 原题 | 题…...
科大奥瑞物理实验——热电偶特性及其应用研究
实验名称:热电偶特性及其应用研究 1. 实验目的: 掌握电位差计的工作原理和结构特点;了解温差电偶测温的原理和方法;学会电位差计的使用及注意事项。 2. 实验器材: 电位差计 标准电池 光电检流计 稳压电源 温差电偶…...
Eclips快捷键大全(超详细)
Eclips快捷键大全(超详细)前言一、常用快捷键二、编辑快捷键三、导航快捷键四、运行和调试快捷键五、重构快捷键六、代码生成快捷键七、项目导航快捷键八、帮助快捷键九、搜索快捷键十、标记快捷键十一、版本控制快捷键十二、其它快捷键前言 本博主将用C…...
整懵了,蚂蚁金服4面成功拿下测开offer,涨薪10k,突然觉得跳槽也不是那么难
蚂蚁的面试挺独特的,每轮面试都没有HR约时间,一般是晚上8点左右面试官来一个电话,问是否能面试,能的话开始面,不能就约一个其他时间。 全程4面,前四面技术面,电话面试,最后一面是HR面…...
C++内存分布malloc-free-new-delete的区别和联系
目录 一、内存分布 1.1内存分布图: 1.2 为什么要将bss和data区分开呢? 1.3 堆和栈有什么区别 二、malloc、free;new、delete 2.1 new和delete是如何实现的,new与malloc的异同处 2.2既然有了malloc/free,C为什么还…...
【华为OD机试 2023最新 】 最多颜色的车辆(C++ 100%)
文章目录 题目描述输入描述输出描述用例题目解析C++题目描述 在一个狭小的路口,每秒只能通过一辆车,假设车辆的颜色只有 3 种,找出 N 秒内经过的最多颜色的车辆数量。 三种颜色编号为0 ,1 ,2 输入描述 第一行输入的是通过的车辆颜色信息 [0,1,1,2] 代表4 秒钟通过的车…...
Linux安全加固
一、重要文件 /etc/passwd #记录本地用户的属性信息,如UID、GID /etc/shadow #存放用户的口令信息 只有系统管理员能查看 /etc/pam.d/system-auth #账户安全配置文件 /etc/login.defs #修改登录的配置文件 /etc/profile …...
Java基础学习(6)
Java基础学习一 字符串1.1 API 与 API文档1.1.1 如何使用帮助文档查找想要导用的方法1.2 String 概述1.3 创建String对象的两种方式第一种第二种1.4 Java常用字符串方法1.4.1 比较1.4.2 字符串通过索引取出1.4.3 取出字符串中的单个字符1.4.4 替换出字符串当中的字符1.4.5 取出…...
dw做网站是静态还是动态/网站外链优化方法
1 问题 给定一个非负整数 N,找出小于或等于 N 的最大的整数,同时这个整数需要满足其各个位数上的数字是单调递增。 (当且仅当每个相邻位数上的数字 x 和 y 满足 x < y 时,我们称这个整数是单调递增的。) 示例 1:…...
副食店年报在哪个网站做/北京网站优化排名
概述 Tornado 是 FriendFeed 使用的可扩展的非阻塞式 web 服务器及其相关工具的开源版本。这个 Web 框架看起来有些像web.py 或者 Google 的 webapp,不过为了能有效利用非阻塞式服务器环境,这个 Web 框架还包含了一些相关的有用工具 和优化。 Tornado 和…...
2017我们一起做网站/引擎网站推广法
1.帮助命令: docker version docker info docker --help2.镜像命令: 列出: docker images 列出本地镜像 docker images -a 列出本地所有镜像 包含中间层 docker images -q 只列出Id docker images --digests 显示镜像摘要信息 docker ima…...
长沙建设工程造价网站/网站优化排名易下拉排名
做微信开发,鉴于微信POST的消息是XML数据包,通过SimpleXMLElement Object获取的数据不好操作,需要转化为普通数组。网上找了很多方法都不理想,发现通过json_decode和json_encode可以转化,遂分享给大家。$postStr 134…...
广州网站制作开发/市场调研报告的基本框架
div布局之所以要学懂学透,是因为table的布局实在是难堪大用,如果是同处于一个表格之内, 各行的规格分布根本就没法调, 例如下面的一段非常简单的代码: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transi…...
专注高端网站设计/百度地图的精准定位功能
IntelliJ IDEA 默认需要进行maven的设置 需要指定maven的地址,指定settings.xml的地址; 可以默认的在user/.m2/下面放一个settings.xml文件; 学习:http://www.itkeyword.com/doc/8778346909898588127/intellij-idea-cannot-resolv…...