面试题答案
一键面试常见的Redis热点数据识别方法
- 基于访问频率计数:
- 原理:使用Redis的哈希(Hash)数据结构,为每个数据项设置一个计数器。每次访问数据时,通过
HINCRBY
命令增加对应数据项的访问计数。定期对这些计数器进行排序,访问计数高的数据即为热点数据。 - 示例:假设哈希表名为
hot_data_counter
,数据项key1
被访问时,执行HINCRBY hot_data_counter key1 1
。
- 原理:使用Redis的哈希(Hash)数据结构,为每个数据项设置一个计数器。每次访问数据时,通过
- 基于访问时间:
- 原理:利用Redis的
SET
命令的EXAT
选项(设置过期时间为指定时间戳),每次访问数据时更新其过期时间。最近频繁访问的数据其过期时间会不断更新,通过定期扫描数据的过期时间来识别热点数据。不过这种方式会消耗较多的Redis资源。 - 示例:
SET key1 value1 EXAT <当前时间戳 + 过期时间偏移量>
,每次访问key1
时,重新设置过期时间。
- 原理:利用Redis的
- 布隆过滤器辅助识别:
- 原理:布隆过滤器用于判断一个元素是否在一个集合中。先将所有数据项通过布隆过滤器的哈希函数映射到布隆过滤器的数组中。每次访问数据时,检查布隆过滤器,如果命中则增加该数据的访问计数(同基于访问频率计数方式)。由于布隆过滤器存在误判率,所以可能会将一些非热点数据误判为热点数据,但可以通过调整布隆过滤器的参数来降低误判率。
- 示例:使用Redis的位图(Bitmap)来实现布隆过滤器。比如有三个哈希函数
hash1
、hash2
、hash3
,数据项key
,计算hash1(key)
、hash2(key)
、hash3(key)
对应位图的位置并设置为1。访问时同样计算位置判断是否都为1。
基于Redis实现简单的缓存加载机制
- 数据首次加载:
- 应用层查询:应用程序先尝试从Redis缓存中获取数据,使用
GET
命令。例如,要获取键为user:1
的用户数据,执行GET user:1
。 - 缓存未命中:如果缓存未命中(返回值为
nil
),则应用程序从数据源(如数据库)查询数据。假设使用SQL查询用户表,SELECT * FROM users WHERE id = 1
。 - 缓存写入:从数据源获取到数据后,将数据写入Redis缓存,使用
SET
命令,并设置合适的过期时间。例如,SET user:1 "{'name': 'John', 'age': 30}" EX 3600
,这里设置过期时间为3600秒(1小时)。
- 应用层查询:应用程序先尝试从Redis缓存中获取数据,使用
- 更新策略:
- 主动更新:当数据源中的数据发生变化时,应用程序在更新数据源后,立即更新Redis缓存。例如,用户信息更新后,先执行数据库更新操作
UPDATE users SET name = 'Jane' WHERE id = 1
,然后执行SET user:1 "{'name': 'Jane', 'age': 30}" EX 3600
更新Redis缓存。 - 被动更新:即缓存过期更新。当缓存过期后,应用程序再次请求数据,缓存未命中,按照数据首次加载的流程从数据源获取数据并重新写入缓存。这种方式简单,但可能在缓存过期到重新加载期间,应用程序获取到的数据不是最新的。为了减少这种影响,可以设置较短的缓存过期时间,或者采用缓存击穿预防措施(如互斥锁方式),避免大量请求同时缓存未命中导致数据库压力过大。在互斥锁方式中,当缓存未命中时,先尝试获取互斥锁(如使用
SETNX
命令设置一个锁键),获取到锁的请求去数据源加载数据并写入缓存,然后释放锁;其他未获取到锁的请求等待一段时间后再次尝试从缓存获取数据。
- 主动更新:当数据源中的数据发生变化时,应用程序在更新数据源后,立即更新Redis缓存。例如,用户信息更新后,先执行数据库更新操作