Redis 必备的原理知识要点

1、为什么使用缓存?

1、数据库太慢-无法使用

2、高性能

3、高并发

4、热点高频数据

2、redis合适的场景?

1、数据类型 5种;

2、Bitmap;

3、HyperLogLog;

结合自身项目讲解redis的使用:

1、token;

2、用户权限集合;

3、营销活动高并发访问的内容或数据;

4、验证码;

3、mysql跟redis缓存的一致性如何保证?双写不一致问题

一般采用删除缓存类相关方式,而不是同步更新缓存。

延迟双删

更新db,删除缓存后,延迟一个时间后再删除一次缓存。

数据查询进行缓存的地方需要查询master,避免MySQL主从同步的影响。

4、缓存穿透、击穿、雪崩是什么?怎么避免?

1、缓存穿透,数据本身不存在,请求打到mysql,造成拥堵;

2、击穿:过期瞬间,高并发打到mysql上,造成拥堵;

3、雪崩:同一时间大批量失效或缓存宕机,多种不同的业务请求db查询打到mysql上,造成拥堵;

解决穿透

1、缓存不存在的数据,而不是不缓存。比如存储一个特殊容易识别的字符串。

2、如果是客户端之间提供的key,那么key可以做一些巧妙设计,key自校验;

3、使用布隆过滤器,大概率过滤掉不存在的key;(不在的一定不在,在的可能不在)

4、添加限流等安全机制,限制恶意访问;

可以使用两个Bitmap,采用不一样的哈希算法,那么可以降低 存在的可能不存在 这种现象。

解决击穿

1、多级缓存;

2、提前感知热点数据,预加载提前延长时间;

3、正确评估,设置合理的过期时间;

4、主动感知提前预警;

解决雪崩

1、不同key的TTL添加随机时间戳;ttl岔开;

2、提前感知热点数据,预加载提前延长时间;

3、正确评估,设置合理的过期时间;

4、redis采用集群模式,一主多从,提升redis HA能力;

5、主动感知提前预警;

5、redis集群模式的架构模型分析

redis-cluster  3.0版本以上提供;

16384 个槽,分片设计。

为什么 16384?

对于节点在1000以内的redisCluster 16384个槽位够用了。如果超过1000个节点,节点之间的 ping/pong 消息占用带宽消耗损耗过大。

相比单机的限制

mset、mget 需要保证同slot操作。

事务支持也需要保证同slot。

可能会造成热点数据分配不均匀,数据倾斜的问题。

不应该使用不同的数据库(db0-db15)来存储同一应用程序的不同数据。而是应该使用相同的数据库,但使用不同的key来区分不同的数据。因此,应该使用不同的Redis实例来存储不同的应用程序的数据

当使用Redis Cluster时,只支持使用db0。

Redis Cluster 每个节点只有一个数据库(即 db0),这是 Redis Cluster 的默认设置。但是,阿里云 Redis 集群是基于 Redis Cluster 构建的高可用解决方案,它使用了分片技术,在 Redis Cluster 的基础上增加了分片功能,将一个 Redis 数据库划分为多个子数据库。每个子数据库具有独立的物理内存和存储空间,这些子数据库可以被称为 db1,db2,...,db255 等等。这种方式提高了阿里云 Redis 集群的可用性和可伸缩性,同时也为用户提供了更好的灵活性和可定制性,以满足不同应用场景下的需求。

集群原理:

Redis Cluster将所有数据划分为16384个slots(槽位),每个节点负责其中一部分槽位,槽位的信息存储在每个节点中;当Redis Cluster的客户端连接集群时,它也会得到一份集群的槽位配置信息缓存在本地,这样可以根据key值定位到目标节点;槽位与服务端机器不一致问题需要纠正机制来实现槽位校验调整;

集群选主:

1.slave发现自己的master变为FAIL;
2.将自己记录的集群currentEpoc 并广播FAILOVER AUTH REQUEST 信息;
3.其他节点收到该信息,判断请求者的合法性,并发送FAILOVER AUTH ACK,对每一个epoch只发送一次ack;
4.尝试failover的slave收集master返回的FAILOVER AUTH ACK;

5.slave收到超过半数master的ack后变成新Master(这里解释了集群为什么至少需要三个主节点,如果只有两个,当其中一个挂了,只剩一个主节点是不能选举成功的);

6.slave广播Pong消息通知其他集群节点;

延时发送拉票请求计算公式:

DELAY=500ms+random(0-500ms)+ SLAVE RANK*1000ms
'SLAVE RANK表示此slave已经从master复制数据的总量的rank,Rank越小代表已复制的数据越新,这种方式下,持有最新数据的slave将会首先发起选举(埋论上)。

redis 集群脑裂问题:

网络分区导致,一旦网络分区恢复,会将其中一个主节点变为从节点,这时会有大量数据丢失。

集群扩容

1 节点加入集群(加入后节点默认都是master节点);

2 槽位重新分配(连接任何机器 发起槽位分配,指定分配数量 ,指定分配到的机器,被分配的节点),数据也会跟着迁移;

3 加入副本节点,将副本节点指定为之前加入成为master节点的副本节点;

6、大key会存在什么问题?大key如何优化?

大key会造成网络拥堵。

拆分大key,可以将网络压力分散到多个分片上,以解决大key集中在某个分片上造成拥堵的问题。

大key在 Redis 中会导致一些潜在的问题和性能影响,主要包括以下几点:

  1. 内存占用过大:大key会占用大量的内存空间,如果一个键的大小远超过其他键,可能会导致 Redis 实例的整体内存使用不均衡。

  2. 影响性能:操作大key可能会消耗更多的网络带宽和 CPU 资源。例如,对大字符串进行读写操作可能会阻塞 Redis 的主线程,导致其他操作的延迟。

  3. 增加数据失效时间:当一个键被删除或者过期时,如果该键是大key,它的删除操作可能会比其他键更加耗时,因为 Redis 在删除大key时需要处理更多的数据。

为了优化大key的问题,可以考虑以下几种策略:

  1. 分割大key:将一个大key拆分成多个小key。例如,将一个大的哈希表分成多个小的哈希表,每个小哈希表存储部分数据。

  2. 使用合适的数据结构:选择合适的数据结构来存储数据。例如,如果一个列表中的元素数量过大,可以考虑使用分片列表(例如 Redis 的 Stream)来代替。

  3. 控制数据大小:对于字符串类型的大key,可以考虑是否可以分批次处理或者压缩数据。如果数据可以分段处理,可以减少一次操作中的数据量。

  4. 使用合理的 TTL(生存时间):如果大key不需要永久存储,考虑设置合适的 TTL。这样可以确保大key在一定时间后自动删除,避免长时间占用内存。

  5. 避免频繁的大key操作:在设计应用程序时,尽量避免频繁地操作大key,特别是读写操作。可以考虑通过异步处理或者分批次处理来优化。

  6. 本地缓存。

总之,合理设计和管理大key对于保持 Redis 的性能和稳定性至关重要。

7、redis 淘汰机制,删除策略 介绍

淘汰策略

Redis 的淘汰机制指的是在内存不足时,Redis 选择哪些键进行删除以释放内存的策略。Redis 提供了几种不同的淘汰策略,这些策略可以通过配置来选择适合特定应用场景的方式。

以下是 Redis 中常见的淘汰策略:

  1. No Eviction (无淘汰策略):

    • 当内存不足以容纳新写入数据时,Redis 不会删除任何键,而是直接返回一个写入错误(OOM 错误)给客户端。
  2. Allkeys-LRU (最近最少使用)

    • Redis 会从所有键空间中选取最近最少使用的键进行淘汰。LRU 算法基于最近的访问时间来决定哪些键最久未被使用,优先删除最长时间未被访问的键。
  3. Allkeys-LFU (最不常用)

    • Redis 会从所有键空间中选取最不常用的键进行淘汰。LFU 算法基于键被访问的频率来决定,优先删除访问频率最低的键。
  4. Volatile-LRU (带过期时间的最近最少使用)

    • Redis 会从设置了过期时间的键空间中选取最近最少使用的键进行淘汰。这种策略仅会考虑带有过期时间的键,而不会考虑持久化的键。
  5. Volatile-LFU (带过期时间的最不常用)

    • Redis 会从设置了过期时间的键空间中选取最不常用的键进行淘汰。与Volatile-LRU 类似,但是基于访问频率而不是最近访问时间来决定。
  6. Volatile-TTL (带过期时间的TTL)

    • Redis 会基于键的 TTL(Time-To-Live,生存时间)来决定淘汰。具体来说,Redis 会优先删除那些 TTL 较短的键,以释放更多的空间给 TTL 较长的键使用。

配置和选择策略

你可以通过配置 Redis 的 maxmemory-policy 参数来选择使用哪种淘汰策略。例如,可以在 Redis 配置文件中设置如下:

maxmemory-policy <policy>

其中 <policy> 可以是以下之一:

  • noeviction
  • allkeys-lru
  • allkeys-lfu
  • volatile-lru
  • volatile-lfu
  • volatile-ttl

默认情况下,Redis 使用 noeviction 策略,即不进行任何淘汰操作,当内存不足时会产生 OOM 错误。在实际应用中,根据你的数据访问模式和内存使用情况,选择合适的淘汰策略非常重要,可以有效地提升性能和内存利用率。

过期删除策略

Redis 中有两种主要的过期删除策略,它们决定了过期键的删除方式:

  1. 定期删除(定时删除)

    • Redis 默认使用的过期删除策略。它通过定期检查随机抽取的一些过期键,并删除其中已经过期的键来释放内存。这个过程并不是严格按时进行的,而是通过一个定时器以及每次执行时删除的键数来控制的。

    Redis 通过两个配置参数来控制定期删除策略:

    • hz:表示 Redis 的时间周期,每秒钟运行的周期数,默认为 10 次。
    • maxmemory_samples:每次运行周期内检查的键数目,默认为 5 个。

    这种策略的优点是不会阻塞 Redis 的主线程,因为删除操作被分散到不同的时间点进行。

  2. 惰性删除(懒汉式删除)

    • 惰性删除策略是指在访问键时,Redis 会先检查键是否过期,如果过期则删除。这意味着过期键只有在被访问时才会被删除,如果键已过期且未被访问,则会保留在内存中直到被访问时进行删除。

    这种策略的优点是可以确保不会在定期删除操作时花费太多 CPU 时间,因为只有在需要访问过期键时才会进行删除操作。然而,缺点是可能会导致过期键在内存中较长时间滞留。

淘汰策略与过期删除策略的区别

虽然淘汰策略和过期删除策略都涉及到 Redis 内部键的删除,但它们的目的和机制略有不同:

  • 淘汰策略 主要用于处理内存不足时如何删除键来释放空间,是为了管理内存的使用和控制。例如,LRU、LFU 等策略。
  • 过期删除策略 则专注于处理带有过期时间的键,在键的过期时间到达后如何及时从内存中删除以节省空间。

这两种策略在 Redis 中共同作用,帮助确保数据的有效性和内存的有效利用。

8、redis 持久化机制是怎么样的?

RDB

快照模式,耗时较久。定时rdb,会存在缓存数据丢失的问题。 丢失

AOF

命令追加文件,日志持久化,实时存储操作命令,日志恢复缓存较慢;性能差

结合二者混合持久化

大部分的数据采用RDB进行恢复,增量的数据采用AOF进行同步。 推荐

9、redis 分布式锁是如何实现的?

1、setNotExist,原子性保证;

2、ttl设置过期时间,合理评估时间;

3、看门狗模式,守护线程-伴随客户端启动,锁续期,这样锁就不需要一开始就设置很长过期;

4、谁加的锁谁来删除,所以每次加锁需要使用唯一随机value值,解锁时需要判断value值 --- lua script模式;

10、redis是单线程的,为什么依然这么快?

1、内存操作;

2、单线程避免线程上下文切换,避免资源竞争-线程安全-加锁等;

3、渐进式ReHash缓存时间戳的使用;

4、IO模型-多路复用,redis6.0开始,随着硬件网卡速度的提升,redis在IO层面做了多线程的优化,提升了数据从内核到用户态,用户态到内核态的数据的传递。

5、CPU不是瓶颈!cpu使用率不高。受制的是网络、内存空间;

全局hash表

两张哈希表:

渐进式ReHash解决扩容影响redis性能的问题。采用分摊操作的方式,让IO不会集中阻塞。

为何6.0以后又要引入多线程?

1、小数据包,是否多线程IO,没有影响;

2、qps需求极高的场景,大量数据包时就需要提升网络读写的性能了,硬件网卡能力也确实可以支持这个升级。

3、可以适当利用CPU的资源;

从IO操作与多线程的思考到Redis-6.0-CSDN博客

11、redis网络IO模型是什么样的?

IO多路复用,select、poll、epoll。

从IO操作与多线程的思考到Redis-6.0-CSDN博客

Linux网络模型浅析-CSDN博客

12、redis数据类型结构原理分析。

万字长文的Redis五种数据结构详解(理论+实战),建议收藏。-腾讯云开发者社区-腾讯云

13、redis 使用的注意事项有哪些?

1、建议使用批量操作提高效率,Pipeline 命令批量处理; 每秒 100W;

2、key设计

  • 以业务名为key前缀,用冒号隔开,以防止key冲突覆盖。如,live:rank:1

  • 确保key的语义清晰的情况下,key的长度尽量小于30个字符。

  • key禁止包含特殊字符,如空格、换行、单双引号以及其他转义字符。

  • Redis的key尽量设置ttl,以保证不使用的Key能被及时清理或淘汰。

3、坚决避免大 key;

  • 如果是String类型,单个value大小控制10k以内。

  • 如果是hash、list、set、zset类型,元素个数一般不超过5000。

4、合适的数据类型;

要选择适合的数据类型。不少小伙伴只用Redis的String类型,上来就是set和get。实际上,Redis 提供了丰富的数据结构类型,有些业务场景,更适合hash、zset等其他数据结果。

反例:

set user:666:name jayset user:666:age 18复制代码

正例

hmset user:666 name jay age 18 复制代码

5、给Key设置过期时间,同时注意不同业务的key,尽量过期时间分散一点;

参考文章:百度安全验证

14、redis-lua脚本执行的意义是什么?有没有需要注意的点?

1、可以保证脚本中的逻辑不会被其它redis访问指令中断;

2、集群模式下 lua脚本中操作多个key,key需要在同一个哈希slot中。

3、可以先script load,然后得到一个哈希字符串,存储,然后使用EavalSha 执行,提升效率;

执行 Redis Lua 脚本的主要意义在于提供了一种在服务端执行复杂操作的机制,以及通过原子性操作来确保数据一致性。以下是需要注意的几个重点:

  1. 原子性操作:Redis 的 Lua 脚本会被作为一个整体原子性地执行,这意味着在脚本执行期间,不会被其他客户端的命令中断。这对于需要多个 Redis 命令组合执行以确保数据一致性的场景非常有用。

  2. 减少网络开销:与传统的多个命令依次执行相比,Lua 脚本可以减少网络开销,因为脚本可以在一次通信中完成多个操作。

  3. 复杂逻辑支持:Lua 脚本支持条件判断、循环、函数等复杂逻辑,使得可以在服务端执行更复杂的计算和操作,而无需将数据传输到客户端进行处理。

  4. 缓存复用:可以通过 EVALSHA 命令将 Lua 脚本的 SHA1 校验和缓存到 Redis 中,以便重复使用相同脚本,减少每次执行时的传输开销和服务器端的解析开销。

  5. 性能考量:尽管 Lua 脚本在 Redis 中执行效率很高,但是复杂的脚本或者大数据量的操作可能会影响 Redis 的整体性能。因此,在编写 Lua 脚本时应尽量保持简洁高效。

  6. 安全性:Lua 脚本是在 Redis 服务器端执行的,因此应避免在脚本中执行不受信任的代码,以防止可能的安全漏洞。

  7. 错误处理:Lua 脚本的执行结果可能返回错误信息,应该对执行结果进行适当的错误处理和容错处理,以确保系统的稳定性。

综上所述,Redis Lua 脚本执行能够有效提升 Redis 在复杂逻辑和数据一致性上的处理能力,但在使用时需要注意上述几点,以确保脚本的安全性、效率和稳定性。

15、redis集群-分布式模式,会存在哪些问题?

16、redis有哪些高级功能?

1、Pipeline;RTT ,可以节约往返时间。

2、Lua脚本,绑定多个key的操作,做一些逻辑处理;

3、分布式锁;

17、Redis主从复制的过程及原理

Redis详解(4)- 主从复制原理-腾讯云开发者社区-腾讯云

1、全量同步

2、增量同步

3、实时同步

18、Redis HA模式有哪些?

三种:主从模式、哨兵、cluster集群分片模式(分布式);

关于哨兵模式:

19、Redis 跟 Memcached 比较

redis支持的类型多,功能更加全面;

redis 支持持久化功能。

Redis 相对于 Memcached 在当前技术选择中更为流行的几个主要原因包括:

  1. 数据结构的丰富性: Redis 不仅仅是一个简单的键值存储系统,它支持丰富的数据结构,如字符串、哈希表、列表、集合、有序集合等。这些数据结构的支持使得开发者可以更灵活地存储和操作数据,而不仅仅局限于简单的键值对。

  2. 持久化支持: Redis 支持多种持久化方式,可以将内存中的数据持久化到磁盘上,保证数据的安全性。这使得 Redis 不仅可以作为缓存使用,还可以作为持久化存储的一部分。

  3. 性能优化: Redis 是基于内存的数据库,相比 Memcached 在某些场景下能提供更高的性能。Redis 通过支持事务、持久化、复制等特性,使得其在性能和功能上都有很好的平衡。

  4. 复制和高可用性: Redis 支持主从复制和 Sentinel(哨兵)机制,能够提供高可用性和容错能力。这使得 Redis 在处理大规模应用和需要高可靠性的场景中更具优势。

  5. 社区和生态系统: Redis 有着活跃的社区支持和丰富的生态系统,有很多开源工具、库和扩展,可以方便开发者使用和集成。

  6. 灵活的配置选项: Redis 提供了丰富的配置选项和命令,可以根据具体的应用场景进行调整和优化,使得其适用于多样化的需求。

尽管 Memcached 仍然在某些场景下有其优势,例如在简单的键值缓存和分布式处理中性能表现出色,但是随着应用需求的复杂化和性能要求的提升,Redis 提供了更多的功能和灵活性,因此在当前大多数应用场景下更为流行和广泛使用。

20、分布式锁如何选择?

redis分布式锁:

1、setNotExist,原子性保证;

2、ttl设置过期时间,合理评估时间;

3、看门狗模式,守护线程-伴随客户端启动,锁续期,这样锁就不需要一开始就设置很长过期;

4、谁加的锁谁来删除,所以每次加锁需要使用唯一随机value值,解锁时需要判断value值 --- lua script模式;

zk分布式锁介绍:

在 ZooKeeper(简称zk)中实现分布式锁的原理通常基于它的临时顺序节点(ephemeral sequential nodes)和 Watch 机制。下面是实现分布式锁的基本原理:

  1. 创建临时顺序节点

    • 当一个客户端需要获取锁时,它会在 ZooKeeper 的特定路径下创建一个临时顺序节点。
    • 每个节点的名称都是唯一且按照顺序递增的,例如 /locks/lock-000000001/locks/lock-000000002 等。
  2. 获取锁

    • 客户端获取所有子节点的列表,并判断自己创建的节点是否是最小的(即序号最小)节点。
    • 如果是最小节点,则表示客户端成功获取了锁;如果不是,则客户端监听比自己小一位的节点(通过 Watch 机制)。
  3. Watch 机制

    • 如果客户端的节点没有获取到锁(即不是最小节点),则客户端会对比自己的节点和前一个节点(序号减一)的关系。
    • 客户端会设置 Watch 监听前一个节点,当前一个节点被删除(即锁被释放)时,ZooKeeper 会通知该客户端。
    • 收到通知后,客户端再次尝试获取锁。
  4. 释放锁

    • 客户端释放锁时,直接删除自己创建的临时顺序节点。
    • 如果客户端因为某种原因断开连接,ZooKeeper 会自动删除该客户端创建的临时节点,从而释放锁。

通过上述步骤,ZooKeeper 实现了基于临时顺序节点的分布式锁机制:

  • 每个客户端创建的节点都是临时的,因此在客户端断开连接时会自动删除,避免了锁的过长占用。
  • 客户端通过监视比自己小一位的节点来实现自旋锁的效果,确保在锁被释放时能够及时获取通知。

这种基于 ZooKeeper 的分布式锁机制能够保证在分布式环境下,各个节点之间能够协调对共享资源的访问,确保了分布式系统的数据一致性和并发控制。

选择使用 ZooKeeper 分布式锁还是 Redis 分布式锁,通常取决于具体的应用场景和需求。以下是它们各自的特点和适用场景:

ZooKeeper 分布式锁

特点

  • 基于 ZooKeeper 的临时顺序节点和 Watch 机制实现。
  • ZooKeeper 是一个分布式协调服务,提供强一致性和顺序访问控制。
  • 可以保证全局的锁顺序和唯一性。
  • 支持复杂的分布式协调场景,不仅限于锁。

适用场景

  • 强一致性要求高的场景:ZooKeeper 提供了强一致性,适合需要确保数据一致性和可靠性的场景。
  • 复杂的分布式协调:ZooKeeper 不仅仅是锁服务,还可以用于分布式配置管理、领导选举等复杂的分布式协调任务。
  • 需要较为复杂的锁管理逻辑:ZooKeeper 提供了更多的灵活性,可以实现更复杂的锁管理逻辑,例如读写锁、公平锁等。

Redis 分布式锁

特点

  • 基于 Redis 的 SETNX(Set if Not eXists)和 EXPIRE 命令实现。
  • 简单且易于实现。
  • Redis 是内存数据库,读写性能优秀,适合高并发场景。
  • 支持的锁类型较简单,通常是互斥锁。

适用场景

  • 高并发的分布式环境:Redis 的性能非常出色,适合高并发的场景。
  • 简单的互斥控制:如果仅需简单的互斥控制,Redis 提供了简单易用的 SETNX 和 EXPIRE 命令来实现分布式锁。
  • 短时间的锁定:Redis 的锁通常是基于超时时间的,适合需要自动释放的场景。

如何选择

  1. 一致性和复杂性需求

    • 如果应用需要强一致性和复杂的分布式协调,例如选主、配置管理等,应考虑使用 ZooKeeper。
    • 如果只需要简单的锁定和释放,且对一致性要求不高,Redis 提供的简单分布式锁可能更合适。
  2. 性能和简易性

    • 如果应用对性能有较高要求,并且锁的逻辑较简单,Redis 可能是更好的选择。
    • 如果需要复杂的锁管理逻辑或者保证强一致性,尽管 ZooKeeper 在性能上可能不如 Redis,但它提供了更多的功能和一致性保证。
  3. 系统架构和成本

    • 考虑系统架构中已有的组件和成本,如果已经使用了 ZooKeeper 作为分布式协调服务,添加锁功能可能更为简单和成本效益高。
    • 如果系统中已经广泛使用 Redis,并且需要的锁的逻辑简单,直接使用 Redis 可能更加便捷。

综上所述,选择 ZooKeeper 还是 Redis 分布式锁应根据具体的业务需求、性能要求和现有架构来综合考虑。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

进窄门见微光行远路

如果对你有比较大的帮助

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值