【Redis】个人笔记

一、什么是Redis

Redis是一个开源的内存数据存储系统,也是一个高性能的键值存储数据库。它支持多种数据结构,包括字符串、哈希表、列表、集合以及有序集合。Redis的特点是快速、灵活和可扩展。

首先,Redis是一个内存数据存储系统,这意味着它将所有数据存储在内存中,因此具有非常快的读写速度。相比于传统的磁盘存储系统,Redis可以提供非常低的读写延迟,使得它非常适合需要快速响应的应用场景,如缓存、实时计算等。

其次,Redis支持多种数据结构。除了最基本的字符串类型,Redis还支持哈希表、列表、集合和有序集合等数据结构。这使得开发者可以根据自己的需求选择最适合的数据结构,并可以利用这些数据结构来实现更复杂的功能。例如,哈希表可以用来存储对象,列表可以用来实现队列和栈,集合可以用来存储唯一值,有序集合可以用来实现排行榜等。

此外,Redis还具有一些特殊的功能。它可以通过持久化机制将数据存储到硬盘上,以防止内存数据丢失。它还支持发布-订阅模式,使得不同的客户端可以通过订阅频道来接收消息。此外,Redis还提供了事务和 Lua 脚本功能,使得开发者可以执行一系列操作来保证数据的一致性。

另外,Redis还具有良好的可扩展性。它支持主从复制,可以将数据复制到多个节点上,提高数据的可用性和容错性。此外,Redis还支持集群模式,可以将数据分布在多个节点上,提供更高的性能和容量。

总而言之,Redis是一个快速、灵活和可扩展的内存数据存储系统,广泛应用于各种场景,包括缓存、实时计算、消息队列等。它的简单易用和高性能使得它成为许多开发者和企业的首选。

二、数据结构

Redis支持多种数据结构,每种结构都有其独特的用途和应用场景。以下是常见的Redis数据结构及其应用场景:

  1. String(字符串):
    • 应用场景: 存储用户信息、缓存数据、计数器等。
    • 例子: SET key value, GET key.
  2. Hash(哈希表):
    • 应用场景: 存储对象的字段和值,适合存储用户信息、配置信息等。
    • 例子: HSET key field value, HGET key field.
  3. List(列表):
    • 应用场景: 存储有序的元素,适合消息队列、最新消息列表等。
    • 例子: LPUSH key value, LRANGE key 0 -1.
  4. Set(集合):
    • 应用场景: 存储无序不重复的元素,适合关注列表、标签等。
    • 例子: SADD key member, SMEMBERS key.
  5. Zset(有序集合):
    • 应用场景: 存储带有分数的有序元素,适合排行榜、范围查找等。
    • 例子: ZADD key score member, ZRANGE key 0 -1 WITHSCORES.
  6. Bitmap(位图):
    • 应用场景: 存储二进制位,适合记录用户的签到情况、在线状态等。
    • 例子: SETBIT key offset value, GETBIT key offset.
  7. HyperLogLog:
    • 应用场景: 用于基数估算,适合统计网站的独立访客数等。
    • 例子: PFADD key element, PFCOUNT key.
  8. List、Set、Zset的过期时间:
    • 应用场景: 可以给List、Set、Zset设置过期时间,适合缓存、临时数据等。
    • 例子: EXPIRE key seconds, TTL key.
  9. Bloom Filter(布隆过滤器):
    • 应用场景: 快速判断元素是否存在于一个大集合中,适合缓存击穿、分布式系统的唯一性判断等。
    • 例子: 通常需要通过编程语言的库来使用布隆过滤器。
  10. Geo(地理信息):
    • 应用场景: 存储地理位置信息,适合附近的人、地理围栏等。
    • 例子: GEOADD key longitude latitude member, GEORADIUS key longitude latitude radius m.

这些数据结构提供了灵活的存储方式,可以满足不同应用场景的需求。在设计系统时,根据具体的业务需求选择合适的数据结构是很重要的。

三、缓存穿透

缓存穿透是指在使用缓存系统时,某个请求查询的数据在缓存中不存在,也不在后端存储系统中,导致每次请求都要访问后端存储系统,从而增加了系统的负载压力,严重影响系统的性能。

缓存系统的设计初衷是为了提高系统的性能和响应速度。当一个请求到达系统时,系统首先会查询缓存,如果缓存中存在该数据,则直接返回给用户,减少了对后端存储系统的访问。但是,当请求查询的数据不存在于缓存中时,系统仍然需要从后端存储系统中获取数据,并将其存入缓存,供后续请求使用。这就是缓存的正常流程。

然而,如果恶意攻击者针对系统中不存在的数据进行大量请求,这些请求会绕过缓存直接访问后端存储系统,导致后端存储系统承受巨大的负载压力。这种情况下就发生了缓存穿透。

缓存穿透可能会造成以下问题

  • 性能问题:由于每次请求都要访问后端存储系统,系统的响应时间变慢,影响用户体验。

  • 资源浪费:大量无效的请求会占用系统的计算资源和网络带宽,浪费了宝贵的系统资源。

为了解决缓存穿透问题,可以采取以下几种措施

  • 布隆过滤器:使用布隆过滤器来过滤掉一部分恶意请求。布隆过滤器是一种概率型数据结构,可以判断一个元素是否在集合中,被广泛用于缓存穿透的解决方案中。

  • 缓存空值:当后端存储系统查询不到数据时,也将空值存入缓存。这样,在下一次请求查询相同数据时,就可以直接从缓存中获取空值,而不需要再次访问后端存储系统。

  • 设置短暂的过期时间:对于缓存中不存在的数据,可以给其设置一个较短的过期时间。这样,在过期时间内,即使有大量请求查询该数据,也能够直接从缓存中获取,而不需要访问后端存储系统。

  • 异步加载数据:当发现某个请求查询的数据不存在于缓存中时,可以异步地去后端存储系统中加载数据,并将其存入缓存。这样可以避免在查询时阻塞请求线程,提高系统的并发性能。

综上所述,缓存穿透是指恶意请求查询缓存中不存在的数据,导致每次请求都需要访问后端存储系统,造成系统性能下降和资源浪费。为了解决这个问题,可以采取布隆过滤器、缓存空值、短暂过期时间和异步加载数据等措施来提升系统的性能和稳定性。

四、缓存击穿

缓存击穿是指在使用缓存系统时,某个热点数据过期或被删除,而此时又有大量并发请求同时访问该数据,导致缓存系统无法命中并且每个请求都要访问后端存储系统,从而造成后端存储系统的压力过大,严重影响系统的性能。缓存的设计初衷是为了提高系统的性能和响应速度。当一个请求到达系统时,首先会查询缓存,如果缓存中存在该数据,就可以直接返回给用户,避免了访问后端存储系统的开销。然而,当某个热点数据过期或被删除时,如果此时有大量并发请求同时访问该数据,这些请求会绕过缓存直接访问后端存储系统,导致后端存储系统承受巨大的负载压力,而且每个请求都要进行独立的查询和加载数据,重复的工作浪费了系统资源。

缓存击穿可能会造成以下问题

  • 性能问题:由于每个请求都要访问后端存储系统,系统的响应时间变慢,影响用户体验。

  • 资源浪费:大量无效的请求会占用后端存储系统的计算资源和网络带宽,浪费了宝贵的系统资源。

为了解决缓存击穿问题,可以采取以下几种措施

  • 加锁机制:通过在缓存查询的关键代码段加锁,使得只有一个线程可以从后端存储系统加载数据,并将加载的结果存入缓存。其他并发请求在等待锁释放后,直接从缓存获取数据。

    预加载数据:在热点数据过期前主动加载数据并存入缓存,避免数据过期时出现大量并发请求同时访问。

  • 使用互斥锁:在缓存失效时,只允许一个线程从后端存储系统加载数据,并将结果存入缓存。其他线程在等待期间直接从缓存获取数据,避免重复的查询操作。

  • 降低数据过期时间:合理设置缓存数据的过期时间,避免过长的过期时间导致数据过期后出现缓存击穿的情况。

综上所述,缓存击穿是指热点数据过期或被删除,而此时有大量并发请求同时访问该数据,导致缓存系统无法命中并且每个请求都要访问后端存储系统,从而造成后端存储系统的压力过大。为了解决这个问题,可以采取加锁机制、预加载数据、使用互斥锁和降低数据过期时间等措施来提升系统的性能和稳定性。

五、缓存雪崩

缓存雪崩是指在使用缓存系统时,大量的缓存数据同时失效或被删除,导致多个请求同时访问后端存储系统,从而使得后端存储系统无法承受如此大的负载压力,严重影响系统的性能和可用性。缓存的设计初衷是为了提高系统的性能和响应速度。当一个请求到达系统时,首先会查询缓存,如果缓存中存在该数据,就可以直接返回给用户,避免了访问后端存储系统的开销。然而,当大量的缓存数据同时失效或被删除时,如果此时有大量并发请求同时访问后端存储系统,后端存储系统会受到巨大的负载压力,可能导致系统崩溃或严重延迟。

缓存雪崩可能会造成以下问题

  • 1.性能问题:由于大量请求同时访问后端存储系统,系统的响应时间变慢,影响用户体验。

  • 2.可用性问题:过多的请求访问后端存储系统可能导致系统崩溃或严重延迟,使得整个系统不可用。

为了解决缓存雪崩问题,可以采取以下几种措施

  • 1.设置合理的缓存过期时间:合理设置缓存数据的过期时间,避免大量缓存数据在同一时间失效。可以通过为不同的数据设置不同的过期时间,使得缓存数据的过期时间分散开来,减少缓存失效的集中发生。

  • 2.缓存数据异步刷新:在缓存数据即将过期时,异步地从后端存储系统加载数据并刷新到缓存中,避免过多请求同时访问后端存储系统。

  • 3.多级缓存策略:引入多级缓存,如本地缓存和分布式缓存,可以在本地缓存失效时从分布式缓存中获取数据,减少直接访问后端存储系统的频率。

  • 4.限流和熔断机制:通过限制并发请求的数量或采取熔断机制,当请求过多时暂停或拒绝一部分请求,保护后端存储系统免受过大的负载压力。

综上所述,缓存雪崩是指大量的缓存数据同时失效或被删除,导致多个请求同时访问后端存储系统,使得后端存储系统无法承受如此大的负载压力。为了解决这个问题,可以采取设置合理的缓存过期时间、缓存数据异步刷新、多级缓存策略和限流熔断机制等措施来提升系统的性能和可用性。

六、持久化机制

  1. RDB(Redis DataBase)

    • 概要: 将内存中的数据以快照的形式定期保存到磁盘。
    • 配置: 通过配置文件设置快照保存的频率和条件。
    • 优点: 恢复速度快,占用空间小。
    • 缺点: 可能会丢失一段时间内的数据。
  2. AOF(Append-Only File)

    • 概要: 记录所有写操作指令,以追加的方式保存到文件。
    • 配置: 通过配置文件设置AOF的同步频率和条件。
    • 优点: 不会丢失数据,适用于高可用场景。(也可能会丢失的)
    • 缺点: 恢复速度相对较慢,占用磁盘空间相对较大。
  3. 混合持久化:

    • 概要: 同时使用RDB和AOF,兼顾快速恢复和数据不丢失的优势。

七、优化机制

  1. 过期策略

    • 概要: Redis可以为每个key设置过期时间,到期自动删除。
    • 配置: EXPIRE key seconds
    • 优点: 避免无用数据长时间存储,释放内存。
  2. LRU(Least Recently Used)

    • 概要: Redis使用LRU算法来淘汰最近最少使用的key。
    • 配置: maxmemory 设置内存最大占用量,maxmemory-policy 设置淘汰策略。
  3. 分区(Sharding)

    • 概要: 将数据分散到多个Redis实例,提高并发读写能力。
    • 优点: 提高横向扩展性,分担单机负载。
    • 缺点: 需要在应用层进行数据的一致性维护。
  4. 优化命令的使用:

    • 概要: 避免使用耗时较长的命令,如keysflushall等。
    • 优点: 减少命令执行时间,提高性能。
  5. 使用数据结构的合理选择:

    • 概要: 根据实际场景选择合适的数据结构,如使用Hash存储对象属性。
    • 优点: 提高查询效率,降低内存占用。
  6. 使用连接池:

    • 概要: 维护一定数量的Redis连接,避免频繁地创建和关闭连接。
    • 优点: 减少连接的开销,提高连接的重用性。
  7. 使用Pipeline:

    • 概要: 将多个命令打包发送,减少网络通信开销。
    • 优点: 提高批量操作的性能。
  8. 适度的数据分片:

    • 概要: 将大数据集切分成多个小的数据片段,提高并发处理能力。
    • 优点: 减轻单一Redis实例的负担。

综合配置持久化机制和优化机制,可以使Redis在数据安全和性能方面取得平衡,满足不同应用场景的需求。

八、单线程却高性能

  1. 内存操作:
    • Redis主要是基于内存的数据库,因此大多数操作都是在内存中完成的,而内存操作速度非常快。
  2. 非阻塞I/O:
    • Redis采用非阻塞I/O模型,通过事件驱动机制处理网络请求。这意味着在进行读写操作时,单线程可以不断地切换任务,提高CPU的利用率,避免等待I/O操作完成而浪费时间。
  3. 单一数据结构的原子性操作:
    • Redis的单线程模型在处理单一数据结构的原子性操作上非常高效。例如,对于字符串(String)的操作,可以在单个CPU时钟周期内完成。
  4. 避免多线程切换开销:
    • 多线程之间的切换会带来一定的开销,而Redis的单线程模型避免了线程切换的开销。在单线程中,不会出现竞态条件,简化了数据访问的同步问题。
  5. 无锁设计:
    • Redis采用无锁设计,避免了多线程之间的锁竞争。这样可以减少了线程间的争用,提高了整体性能。
  6. 数据结构和算法的优化:
    • Redis在内部使用了高效的数据结构和算法,如快速列表、跳表等,这些数据结构在单线程环境下能够提供高性能的操作。
  7. 高效的事件驱动模型:
    • Redis的事件驱动模型非常高效。它使用了高性能的事件库,能够处理大量的客户端请求,而不会因为等待I/O而被阻塞。
  8. 适用于高并发读写场景:
    • 单线程模型适用于高并发的读写场景,因为读操作是非阻塞的,而写操作通过快速处理可以迅速完成。

虽然Redis是单线程的,但在实际应用中,由于上述因素的综合作用,它能够在高并发的情况下表现出色。需要注意的是,虽然单线程模型对于特定的场景非常高效,但并不适用于所有类型的应用。如果在处理大量计算密集型任务的情况下,可能会限制性能。

九、其他

Redis的优势是什么

  • 高性能: Redis主要将数据存储在内存中,因此能够提供非常高的读写性能。
  • 支持丰富的数据结构: Redis支持多种数据结构,适用于不同的应用场景。
  • 持久化: 提供RDB快照和AOF日志两种持久化方式,可以用于数据备份和灾难恢复。
  • 原子操作: Redis支持原子操作,能够在单个命令中执行复杂的操作,确保数据的一致性。
  • 分布式: Redis Cluster支持数据分片,实现横向扩展。

什么是Redis的数据淘汰策略

Redis使用LRU(Least Recently Used)作为默认的数据淘汰策略。当内存不足以存储所有数据时,会优先淘汰最近最少使用的键,以释放空间。

Redis的持久化机制有哪些

  • RDB快照: 将内存中的数据在指定时间点保存到磁盘上的一个快照文件。
  • AOF日志: 记录了执行的写操作,通过重放这些写操作,可以还原数据。

什么是Redis的哨兵模式

哨兵模式是Redis用于高可用性的一种解决方案。它包括一组哨兵节点,用于监控主节点和从节点的健康状况。如果主节点失效,哨兵会选举一个从节点作为新的主节点,确保系统的可用性。

Redis只有单线程吗

Redis是单线程的,主要是指Redis的网络I/O线程,Redis的持久化、集群同步等操作,则是由另外的线程来执行

采用单线程为什么还这么快

Redis4.0版本之前

Redis的大部分操作都是在内存中完成的

单线程你模型避免了多线程之间的竞争

Redis采用了I/O多路复用机制处理大量的客户端Socket请求

Redis4.0版本之后

Redis添加了多线程的支持

但是多线程主要体现在大数据的异步删除功能上

Redis6.0版本之后

新增了多线程i/O的读写并发能力

也采用了多个i/O线程来处理网络请求,因为随着网络硬件的性能提升,Redis的性能瓶颈有时会出现在网络i/O的处理上,所以为了提高网络请求的

在 Redis 6.0 版本之后,也采用了多个 I/O 线程来处理网络请求这是因为随着网络硬件的性能提升,Redis 的性能瓶颈有时会出现在网络 I/O 的处理上

所以为了提高网络 I/O 的并行度,Redis 6.0 对于网络 I/O 采用多线程来处理。但是对于命令的执行,Redis 仍然使用单线程来处理,所以大家不要误解 Redis 有多线程同时执行命令。

相关推荐
丁总学Java1 小时前
缓存穿透 问题(缓存空对象)
redis
Yz98761 小时前
使用sqoop报错
大数据·linux·数据库·hadoop·apache·big data·sqoop
王俊山IT1 小时前
C++学习笔记----7、使用类与对象获得高性能(二)---- 理解对象生命周期(7)
开发语言·c++·笔记·学习
万叶学编程2 小时前
Oracle数据库安装与SQL*Plus使用
数据库·sql·oracle
xuan哈哈哈2 小时前
web基础—dvwa靶场(七)SQL Injection
数据库·web安全·网络安全
tpoog2 小时前
[Linux]自定义shell详解
linux·运维·服务器·数据库·c++
清流君2 小时前
【自动驾驶】控制算法(八)横向控制Ⅳ | 调试与优化——让车辆行驶更平稳!
人工智能·笔记·算法·自动驾驶·控制算法
牢鹅出海2 小时前
Facebook开发者篇 - API拉取广告投放数据对接流程
经验分享·笔记·facebook