3万+长文揭秘一线大厂Redis面试高频考点,整理不易,求一键三连:点赞、分享、收藏
本文,已收录于,我的技术网站 aijiangsir.com,有大厂完整面经,工作技术,架构师成长之路,等经验分享
Redis是一个开源的、基于内存的高性能键值对数据库,支持多种类型的数据结构,如字符串(strings)、列表(lists)、集合(sets)、有序集合(sorted sets)、哈希表(hashes)、位图(bitmaps)、超日志(hyperloglogs)和地理空间索引(geospatial indexes)。由于它的数据是存放在内存中的,这使得Redis能够提供极高的数据读写速度,通常能够达到每秒数十万次的读写操作。Redis还支持数据的持久化,可以将内存中的数据保存到硬盘中,保证数据的安全性。
Redis的主要特点包括:
Redis作为一个高性能的内存键值存储系统,在众多场景下被广泛应用,既有其显著的优点,也存在一些限制和缺点。
尽管存在这些缺点,Redis凭借其出色的性能和灵活性,仍然是许多高负载应用和服务的首选解决方案。正确的使用和适当的架构设计可以帮助最大限度地发挥其优势,同时缓解一些潜在的缺点。
Redis之所以能够提供如此高速的性能,主要是由于以下几个关键因素的结合:
通过这些设计和实现上的优化,Redis能够提供极高的性能,满足高并发、低延迟的应用场景需求。这也是Redis在缓存、消息队列、实时分析等多种场景中被广泛使用的原因。
Redis虽然以其高性能而闻名,特别是在处理大量数据时提供极低的延迟和高吞吐量,但将其作为主数据库使用而不仅仅是缓存,需要考虑以下几个方面的限制和挑战:
因此,虽然Redis以其出色的性能和灵活的数据结构适用于许多场景,如缓存、消息队列、会话存储等,但将其作为主数据库使用时,上述限制可能会导致它不适合所有应用。通常,开发者会结合使用Redis和其他数据库系统(如MySQL、PostgreSQL或MongoDB等),利用各自的优势,以实现更加全面和高效的数据管理和存储解决方案。
Redis的线程模型是其性能高效的关键因素之一。传统上,Redis使用单线程模型来处理客户端的请求,但这并不意味着Redis服务器只有一个线程在运行。下面详细解释Redis的线程模型及其如何工作:
在Redis 6之前,Redis主要使用单个线程来处理所有的命令请求,这意味着在任意时刻,只有一个命令在被执行。这种设计的优点是避免了多线程编程中常见的并发问题,如数据竞争、锁的开销等,使得Redis能够以非常高的效率执行操作。
从Redis 6开始,引入了IO多线程模型,用于改善网络IO的处理效率。需要注意的是,这个多线程模型仅用于网络IO的读写操作,而不是命令的执行。命令执行仍然是单线程的,保持了Redis操作的原子性和一致性。
Redis的线程模型优化了性能和并发处理能力,同时保持了简单和高效的特点。通过将命令执行与网络IO分离,Redis能够在保证操作安全性的同时,充分利用现代多核CPU的性能,提供高吞吐量和低延迟的数据服务。
Redis作为一个高性能的键值存储系统,因其出色的读写速度和灵活的数据结构,被广泛应用于多种场景中。以下是Redis的一些典型应用场景:
Memcached和Redis都是高性能的分布式缓存系统,广泛用于提升大型动态Web应用的速度,减少数据库负载。尽管它们在某些场景下可以互换使用,但两者之间还是存在一些关键的区别:
使用Redis而不是map或Guava做缓存,通常是出于以下几个考虑:
Redis支持多种数据类型,使其能够应对不同的数据存储需求。下面是Redis支持的主要数据类型:
Redis中的Sorted Set(有序集合)和List(列表)是两种不同的数据结构,它们在使用场景和操作上各有特点。以下是它们的异同点:
当Redis的内存用完时,它的行为取决于配置的内存回收策略和最大内存限制。Redis提供了几种内存管理机制来处理内存不足的情况:
Redis允许通过maxmemory-policy配置项来设置内存回收策略,当内存使用达到maxmemory限制时,Redis会根据设置的策略来回收内存。常见的回收策略包括:
Redis作为内存数据库,其性能强依赖于内存的管理和优化。以下是一些Redis内存优化的策略:
通过maxmemory-policy配置合适的内存回收策略,根据实际应用场景选择最合适的策略,如volatile-lru、allkeys-lru、volatile-ttl等,以优化内存使用。
合理使用Redis支持的数据类型,比如使用哈希(Hash)类型存储对象来节省空间,因为当存储多个字段的小对象时,哈希类型比独立的字符串类型更节省内存。
Redis针对小对象提供了压缩编码(如ziplist和intset),这可以显著减少内存使用。这些优化通常是自动进行的,但了解它们的存在可以帮助我们更好地规划数据结构。
使用EXPIRE命令为键设置生存时间(TTL),让Redis自动删除过期的数据,释放内存。
当需要查找符合特定模式的键时,使用SCAN命令代替KEYS命令,因为KEYS命令会一次性加载所有匹配的键,对内存和CPU资源消耗较大。
监控内存碎片率(通过INFO memory命令查看mem_fragmentation_ratio指标),如果内存碎片率过高,可以通过重启Redis服务或使用MEMORY PURGE命令(在Redis 4.0以上版本可用)来减少内存碎片。
Redis 6引入了客户端缓存能力,通过将热点数据缓存在客户端来减轻服务器端的内存压力。
定期使用INFO memory命令监控内存使用情况,使用MEMORY USAGE命令分析特定键的内存使用,帮助识别和优化内存使用热点。
合理配置RDB和AOF持久化策略,虽然主要是为了数据安全,但适时的数据持久化和加载也可以帮助管理内存使用,特别是在需要重启Redis释放内存碎片时。
Redis的KEYS命令用于查找所有符合给定模式的键。尽管它在某些场景下非常有用,但在生产环境中使用时存在一些显著的问题:
为了避免这些问题,推荐使用以下方法代替KEYS命令:
通过使用SCAN命令或者维护索引,可以在不牺牲性能的情况下,有效地查询和管理Redis中的键,从而避免KEYS命令带来的问题。
Redis事务提供了一种将多个命令打包,然后按顺序执行的机制,确保事务内的命令序列可以连续执行,中间不被其他命令请求所打断。Redis的事务通过以下几个关键命令来实现:
标记一个事务块的开始。之后的所有命令都会被加入到队列中,并不会立即执行。
执行所有在MULTI之后加入队列的命令。当执行EXEC时,队列中的所有命令会被连续执行,期间不会插入其他客户端的命令。
取消事务,放弃执行所有已经被加入队列的命令。
监视一个或多个键,如果在执行事务之前这些键被其他命令改变了,那么事务将被打断。WATCH命令可以用来实现乐观锁。
取消WATCH命令对所有键的监视。
一个Redis事务的简单示例:
WATCH mykey
MULTI
INCR mykey
INCR mykey
EXEC
这个事务尝试对键mykey的值进行两次增加。如果在执行事务之前mykey的值被其他客户端改变了,那么这个事务将不会执行。
Redis事务虽然提供了一种执行多个命令的方法,但它的机制与传统数据库的事务有所不同,使用时需要对其特性和限制有充分的了解。
Redis提供了两种主要的数据持久化机制来保证数据的安全性:RDB(Redis Database)和AOF(Append Only File)。这两种机制可以单独使用,也可以同时使用,以达到最佳的数据安全性。下面是对这两种持久化机制的详细介绍:
RDB持久化是通过快照(snapshotting)来实现的,它会在特定的时间间隔保存那一刻的数据快照。
AOF持久化通过记录每个写操作命令来保存数据状态,这些命令会被追加到AOF文件的末尾。
Redis还允许同时使用RDB和AOF,结合两者的优点。在这种配置下,Redis可以从AOF文件中重建状态,以确保操作的完整性,同时也可以定期生成RDB快照,用于快速重启和数据备份。
在选择Redis的RDB和AOF持久化机制时,需要根据应用的具体需求来决定。下面是一些考虑因素,帮助你做出选择:
优点:
适用场景:
缺点:
优点:
适用场景:
缺点:
对于大多数生产环境,推荐同时启用RDB和AOF,以结合两者的优点:
通过合理配置,如调整AOF的重写策略和频率,以及定期生成RDB快照,可以最大限度地提高数据的安全性,同时确保系统的性能。
概述:单机部署是最简单的部署方式,只涉及到一个Redis服务器实例。
适用场景:
优点:
缺点:
概述:主从复制模式涉及一个主服务器和一个或多个从服务器。数据更新操作在主服务器上执行,然后数据的改动会同步到所有的从服务器。
主从复制的原理?
适用场景:
优点:
缺点:
概述:哨兵(Sentinel)系统是基于主从复制模式的自动故障转移解决方案。哨兵负责监控所有Redis服务器,并在主服务器故障时自动将一个从服务器升级为新的主服务器。
工作原理
适用场景:
优点:
缺点:
概述:Redis集群通过分片(Sharding)将数据分布在多个Redis节点上,每个节点存储不同的数据片段。集群模式支持自动分区、数据复制和故障转移。
工作原理:
在 redis cluster 架构下,每个 redis 要放开两个端口号,比如一个是 6379,另外一个就是 加1w 的端口号,比如 16379。
16379 端口号是用来进行节点间通信的,也就是 cluster bus 的东西,cluster bus 的通信,用来进行故障检测、配置更新、故障转移授权。cluster bus 用了另外一种二进制的协议,gossip 协议,用于节点间进行高效的数据交换,占用更少的网络带宽和处理时间。
适用场景:
优点:
缺点:
总的来说,选择哪种部署方案需要根据应用的具体需求、预算以及维护的复杂度等因素综合考虑。对于初学者或小型项目,可以从单机部署开始;对于需要高可用性和扩展性的生产环境,则应考虑使用哨兵系统或集群模式。
Redis处理过期键(expired keys)的机制主要基于两种策略:惰性删除(Lazy Expiration)和定期删除(Periodic Expiration)。这两种策略共同确保了内存的有效管理,同时避免了单个策略可能带来的性能问题。
当Redis用作缓存时,经常需要处理内存不足的情况。为了解决这个问题,Redis提供了多种内存淘汰策略,允许在达到内存上限时自动删除一些键。这些策略可以通过配置maxmemory-policy设置。以下是Redis支持的一些主要内存淘汰策略:
选择哪种内存淘汰策略取决于具体的应用场景:
在将MySQL与Redis结合使用时,确保数据一致性是一个常见的挑战。MySQL作为关系数据库,通常用于持久化存储,而Redis作为内存数据库,常用于缓存。数据一致性问题主要发生在数据更新时,需要同步更新MySQL和Redis中的数据,以避免脏读(读到旧数据)的情况。以下是一些常用的策略来保证MySQL与Redis之间的数据一致性:
为了处理在缓存删除和数据库更新之间可能发生的并发请求,可以采用延迟双删策略:
延迟的目的是为了处理在这个短暂的时间窗口内可能到达的并发读请求,这些请求可能会再次将旧数据加载到缓存中。
如果应用场景对数据一致性的要求非常高,可以考虑在数据库层面使用事务或锁来确保操作的原子性。例如,在更新MySQL数据前获取一个分布式锁,直到Redis缓存也更新完成后才释放锁。这种方法虽然可以提高数据一致性,但会大大降低系统的性能和吞吐量。
这种方法可以异步地处理数据更新,减少直接操作数据库和缓存可能带来的延迟,但需要处理消息队列的可靠性和消费顺序问题。
Redis缓存在提高系统性能、减少数据库压力方面发挥着重要作用,但在使用过程中也可能遇到一些常见问题,如缓存穿透、缓存雪崩和缓存击穿等。
问题描述:缓存穿透是指查询不存在的数据导致请求直接落到数据库上,缓存无法命中,如果恶意攻击或频繁访问这类不存在的数据,将给数据库带来很大压力。
解决策略:
问题描述:缓存雪崩是指在某一个时间点,缓存中大量的或者全部数据都过期失效,导致所有的请求都落到数据库上,造成瞬时数据库访问压力过大,甚至引起数据库崩溃。
解决策略:
问题描述:缓存击穿是指对于某个热点key(大量并发访问),当这个key在缓存中过期的瞬间,持续的大量请求就直接落到数据库上,导致数据库瞬时压力骤增。
解决策略:
在实践中,经常需要结合多种策略来解决缓存相关问题,比如对热点数据采用加锁或队列的方式防止缓存击穿,对可能不存在的数据采用布隆过滤器预防缓存穿透,同时通过设置合理的过期时间和使用Redis持久化功能来防止缓存雪崩。正确的缓存策略和细致的系统设计可以显著提升系统的健壮性和稳定性。
Redis可以利用其内置的数据结构和命令实现简单的消息队列功能,主要通过列表(List)、发布/订阅(Pub/Sub)机制,以及流(Streams)来实现。
Redis的列表数据结构提供了LPUSH/RPUSH命令用于生产消息(向列表中添加元素),以及BLPOP/BRPOP命令用于消费消息(从列表中移除并获取元素)。这种方法简单易用,适合实现基本的消息队列。
生产者示例:
LPUSH myqueue message1
消费者示例:
BRPOP myqueue 30
Redis的发布/订阅模式提供了一种消息广播的机制,允许发布者向一个频道(channel)发布消息,而所有订阅了该频道的订阅者都能接收到这个消息。这种方式适用于需要消息广播的场景。
发布者示例:
PUBLISH mychannel "Hello, Redis!"
订阅者示例:
SUBSCRIBE mychannel
Redis 5.0 引入了流(Streams)数据类型,提供了更复杂的消息队列功能,支持持久化、消费者组(Consumer Groups)、消息确认等高级特性。Streams是Redis对消息队列和日志数据结构的实现,非常适合构建复杂的消息队列和流处理系统。
生产者示例:
XADD mystream * field1 value1 field2 value2
消费者示例(使用消费者组):
XGROUP CREATE mystream mygroup $ MKSTREAM
XREADGROUP GROUP mygroup myconsumer COUNT 1 BLOCK 1000 STREAMS mystream >
通过上述三种方式,Redis可以灵活地实现消息队列的功能,满足不同场景下的需求。选择哪种方式取决于具体的应用场景和对消息队列功能的需求。
在这种方法中,可以利用Redis的有序集合(ZSET)来实现延时队列。将消息以成员(member)的形式存储在ZSET中,使用消息的执行时间作为分数(score)。通过定期轮询ZSET,取出已到执行时间的消息进行处理。
生产消息示例:
ZADD mydelayqueue <timestamp> "message"
消费消息示例:
ZRANGEBYSCORE mydelayqueue 0 <current_timestamp> WITHSCORES LIMIT 0 1
ZREM mydelayqueue "message"
这种方法结合使用了列表(LIST)和BRPOPLPUSH命令。首先将消息存储在一个列表中,然后使用BRPOPLPUSH命令将消息从一个列表转移到另一个列表,并设置超时时间。如果超时时间到了,消息就会被转移,这时就可以处理这个消息了。
生产消息示例:
LPUSH myqueue "message"
消费消息示例:
BRPOPLPUSH myqueue myprocessingqueue <timeout>
Redis的Keyspace通知功能可以用来实现另一种类型的延时队列。通过为每个消息设置一个具有TTL(Time-To-Live)的key,当key过期时,Redis会生成一个过期事件。通过订阅这些事件,可以实现延时任务的触发。
首先,需要开启Redis的Keyspace通知功能,在redis.conf配置文件中设置:
notify-keyspace-events Ex
生产消息示例:
SETEX message:<message_id> <delay> "message content"
消费消息示例:
Redis中的Pipeline(管道)是一种将多个命令打包,然后一次性发送给Redis服务器执行的技术。使用Pipeline可以显著提高Redis操作的效率,特别是在需要执行大量独立命令时。它的主要作用和优点包括:
在没有使用Pipeline的情况下,每执行一个Redis命令,客户端都需要发送一个请求到服务器,然后等待服务器响应。这种“请求-响应”模式在网络延迟较高或需要执行大量操作时会非常低效,因为每个命令的执行都会受到网络延迟的影响。使用Pipeline后,可以一次性发送多个命令到服务器,然后再一次性接收所有命令的执行结果,这样可以显著减少网络传输造成的延迟。
通过Pipeline技术,多个命令可以在Redis服务器上连续执行,而不需要每执行一个命令就等待客户端的下一个请求,这样可以更有效地利用服务器资源,提高命令处理的吞吐量。
假设需要将多个键值对设置到Redis中,不使用Pipeline的方式可能需要这样:
SET key1 value1
SET key2 value2
SET key3 value3
每执行一个SET命令,都需要等待服务器的响应。而使用Pipeline后,这些命令可以打包发送:
# 伪代码,使用Python的redis客户端
pipe = redis.pipeline()
pipe.set('key1', 'value1')
pipe.set('key2', 'value2')
pipe.set('key3', 'value3')
pipe.execute()
虽然Pipeline提高了效率,但也有一些需要注意的地方:
总的来说,Pipeline是优化Redis性能的有效手段,特别适用于需要大量独立Redis操作的场景
Redis中的Lua脚本功能是一个强大的特性,它允许在Redis服务器上原子性地执行多个命令。这意味着可以把一系列操作写成一个Lua脚本,然后作为一个整体执行,而不是客户端和Redis服务器之间多次往返通信执行多个命令。
Lua脚本在执行过程中不会被其他命令打断,整个脚本作为一个原子操作执行。这对于需要多个步骤完成的操作非常重要,确保数据的一致性和完整性,无需担心中途发生变化。
将多个命令封装在一个Lua脚本中执行,减少了客户端与Redis服务器之间的网络往返次数,提高了效率,尤其是在高延迟网络环境中。
Lua脚本支持将复杂的逻辑封装在服务器端,客户端只需要调用执行脚本即可。这样可以在不同的应用和客户端之间复用这些逻辑,减少了客户端的开发工作量,同时也简化了应用逻辑。
对于复杂的数据处理逻辑,使用Lua脚本可以在Redis服务器内部完成,避免了将数据在网络中传输到客户端进行处理的需要,从而提高了整体性能。
Lua脚本使得可以在Redis服务器上直接进行数据处理和计算,而不是在客户端进行。这对于数据聚合、过滤或转换等操作特别有用。
一个简单的Lua脚本示例,实现了原子性地递增键的值并返回新值:
local value = redis.call('INCR', KEYS[1])
return value
这个脚本使用redis.call函数执行INCR命令,递增指定键的值,并返回新的值。在客户端,只需要发送这个脚本到Redis执行即可,例如使用EVAL命令。
虽然Lua脚本在Redis中非常有用,但也需要注意一些事项:
总体而言,Lua脚本为Redis提供了强大的服务器端逻辑处理能力,使得数据处理更加灵活和高效。
RedLock是一种分布式锁的实现算法,由Redis的创造者Antirez(Salvatore Sanfilippo)提出。这种算法旨在解决在分布式系统中安全地获取锁的问题,特别是在基于Redis这种内存数据结构服务器环境下。RedLock提供了一种方法,用于在没有中心化锁服务的情况下,across多个Redis实例安全地协调锁。
RedLock算法的基本思想是使用多个独立的Redis实例来避免单点故障问题,算法的步骤如下:
在Redis中,大key是指那些存储了大量数据的键,如一个包含数百万个元素的列表、集合、哈希表或有序集合。大key在使用过程中会导致多种问题,包括但不限于内存使用高、操作延迟增加、阻塞Redis服务器等。因此,合理处理大key是优化Redis性能和稳定性的重要一环。以下是处理大key的一些策略:
在处理大key之前,首先需要识别它们。可以使用Redis命令或工具来帮助识别:
一旦识别出大key,可以通过分割的方式来处理。根据key的类型,采取不同的分割策略:
直接删除一个大key可能会导致Redis服务器阻塞,影响服务的响应时间。因此,推荐使用渐进式删除方法:
处理大key需要综合考虑数据的使用模式、业务需求和Redis的性能特点,采取适当的策略来优化。正确管理大key对于维护Redis实例的高性能和稳定性至关重要。
Redis作为一个高性能的内存键值数据库,其性能问题通常与内存管理、数据结构选择、配置设置以及客户端使用模式有关。下面是一些常见的性能问题及其解决方案:
问题描述:Redis占用的内存超过了物理内存的大小,导致系统使用交换空间,从而影响性能。
解决方案:
问题描述:对包含大量元素的键进行操作(如删除一个大列表)可能会阻塞Redis,导致延迟增加。
解决方案:
问题描述:不合理的数据类型选择会导致内存浪费或性能下降。
解决方案:
问题描述:客户端和Redis服务器之间的大量网络往返导致性能下降。
解决方案:
问题描述:频繁的磁盘同步操作会影响性能,特别是在使用AOF持久化并配置为每次写入都同步时。
解决方案:
问题描述:虽然Redis是基于单线程模型,但在处理大量请求或执行复杂命令时,CPU可能成为瓶颈。
解决方案:
当客户端访问一个键时,Redis会检查这个键是否已经过期。如果已经过期,Redis在这个时间点才会删除这个键。这意味着,如果一个已经过期的键没有被访问,它就不会被自动删除,因此内存不会被立即释放。
为了减轻仅依赖惰性删除可能导致的内存占用问题,Redis还会定期从数据库中随机测试一些键,并删除其中已经过期的键。但是,这种方法也不保证所有过期的键都会被及时删除。因为定期删除操作只是随机抽查,并不会遍历所有的键。
基于以上两种策略,以下是一些原因导致Redis过期键后内存没有立即释放的情况:
如果过期键未被及时删除导致内存问题,可以考虑以下策略:
Redis突然变慢可能由多种原因引起,这些原因可能涉及到Redis配置、硬件资源、客户端行为等多个方面。以下是一些可能导致Redis性能下降的常见原因及其解决方案:
Redis性能问题的诊断和解决通常需要从多个角度出发,包括但不限于配置优化、资源调整、查询优化等。使用INFO命令检查Redis状态,定位问题源头,并根据实际情况采取相应的解决措施。
Redis集群通过分片(Sharding)来提供数据分布式存储的能力,它使用了一种称为哈希槽(Hash Slot)的技术来实现这一点。在Redis集群中,有16384个哈希槽,这个数字是固定的。每个键通过对其键名进行CRC16哈希计算,然后对16384取模来决定应该分配到哪个哈希槽,每个哈希槽指向存储数据的节点。
选择16384个槽的原因涉及到多个方面的考虑:
16384提供了足够的细粒度,使得数据可以在不同的节点间均匀分布,同时避免了管理过多槽所带来的复杂性和开销。这个数字是在性能、存储效率和操作复杂度之间的一个折中选择。
当需要在节点间迁移槽以实现集群的重新平衡或扩展时,使用16384个槽可以限制因槽迁移所需的网络流量和操作开销。如果槽的数量过多,即使是小规模的调整也可能会导致大量的数据迁移,增加网络压力和迁移时间。
CRC16哈希算法生成的结果是一个16位的哈希值,这意味着理论上可以有65536个不同的结果。Redis选择16384作为槽数量,是因为它是2的14次幂,可以通过简单的取模操作快速计算出一个键应该被分配到哪个槽。这种方法既保证了计算的快速性,也足够在集群环境中分散键,减少热点。
Redis的设计者在实践中测试了不同的槽数量,最终发现16384是在保证性能和管理上的一个较好平衡点。它足够小,使得集群的管理和维护(如配置、监控)相对简单,又足够大,能够支持大规模的集群部署,满足大多数应用场景的需求。
总之,Redis集群选择16384个哈希槽是基于性能、效率和操作简便性的综合考虑。这个设计使得Redis集群能够以较低的管理成本支持高效的数据分布和扩展性。
Redis服务器本身是线程安全的,因为它基于一个单线程模型来处理命令。这意味着在任意时刻,只有一个命令在服务器上被执行,因此不会存在多个命令同时修改同一个数据造成的数据不一致问题。Redis的这种设计简化了并发控制,避免了锁机制带来的复杂性和性能损失,同时也确保了高性能和高吞吐率。
然而,当我们谈论Redis的线程安全问题时,通常是指在客户端操作Redis时的线程安全性。客户端与Redis服务器的交互是否线程安全,取决于所使用的Redis客户端库:
总结而言,Redis服务器端是线程安全的,因为它本质上是单线程执行命令。客户端操作Redis的线程安全性则取决于所使用的客户端库是否支持线程安全,或者是否通过其他机制(如连接池)来确保线程安全。在多线程环境中使用Redis时,开发者需要特别注意这一点。
Redis处理哈希冲突主要依赖于其内部数据结构的设计。Redis使用哈希表作为基础数据结构之一,哈希表在处理键值对时会遇到哈希冲突。Redis解决哈希冲突的方法主要是通过链地址法(Separate Chaining)。
当两个或多个键的哈希值相同,即它们映射到同一个哈希桶时,会产生哈希冲突。Redis通过链地址法来解决这个问题,具体做法如下:
随着存储的键值对数量增加,哈希表的负载因子(即键值对数量与哈希桶数量的比值)会增加,导致冲突的概率上升,进而影响性能。为了维持效率,Redis会根据负载因子和其他条件(如是否处于读写操作中)动态地扩容哈希表:
Redis通过链地址法有效地解决了哈希冲突问题,确保即使多个键哈希到同一个桶,也能通过遍历链表的方式准确快速地访问到每个键。同时,通过动态扩容机制,Redis能够保持哈希表的高效性能,即使在存储大量数据的情况下。这些设计使得Redis能够作为一个高性能的键值存储解决方案。
引用知乎上一个高赞的回答来解释什么是I/O多路复用。假设你是一个老师,让30个学生解答一道题目,然后检查学生做的是否正确,你有下面几个选择:
第一种就是阻塞IO模型,第三种就是I/O复用模型。
Redis的IO多路复用机制允许单个线程高效地监视多个网络连接上的IO事件(如读写准备就绪)。这种机制依赖于操作系统提供的select、poll、epoll(在Linux中)或kqueue(在BSD系统中,包括macOS)等系统调用。通过这种方式,Redis可以在不同的客户端连接间“快速切换”,在一个连接上等待IO操作完成的同时,处理其他连接上的IO请求。
最近无意间获得一份阿里大佬写的刷题笔记,一下子打通了我的任督二脉,进大厂原来没那么难
这是大佬写的, 7701页的BAT大佬写的刷题笔记,让我offer拿到手软
本文,已收录于,我的技术网站 aijiangsir.com,有大厂完整面经,工作技术,架构师成长之路,等经验分享
点赞对我真的非常重要!在线求赞,加个关注我会非常感激!
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。