一.基于redis实现限流功能,有哪几种方式?
1.限流
一段时间内,某行为允许操作的最大次数
2.限流类型
截断限流,固定时间窗口限流,固定窗口内的行为统计,
实现方式:
set limits 0 nx ex 10
incr limits
滑动时间 窗口限流,滑动窗口行为统计,解决窗口间统计异常,容量固定的,速率也是固定的
实现方式:
zadd limits now now
zremrangebyscore limits 0 period
zcard limits
expire limits 10
-- KEYS[1]: 限流key
-- ARGV[1]: 当前时间戳
-- ARGV[2]: 窗口大小(秒)
-- ARGV[3]: 最大请求数redis.call('ZREMRANGEBYSCORE', KEYS[1], 0, ARGV[1] - ARGV[2])
redis.call('ZADD', KEYS[1], ARGV[1], ARGV[1])
local count = redis.call('ZCARD', KEYS[1])
if count > tonumber(ARGV[3]) thenreturn 0 -- 被限流
elsereturn 1 -- 允许通过
end
漏斗限流 ,初始容量,操作数,时间,步伐 (更加细致的限流) redis-cell扩展实现
令牌桶限流 ,
二.redis为什么是单线程?这里的单线程是什么?为什么这么快?
1.redis是不是单线程
redis-server
所有命令处理
网络事件监听
bio-close-file
异步关闭文件
bio-aof-fsync
异步aof刷盘
bio-lazy-free
异步清理大内存
jemalloc-bg-threads
jemalloc后台线程
io-threads
io线程 read/write decode encode
2.这里的单线程是指什么?
命令处理流程在一个线程中处理的
3.redis为什么是单线程
redis不是CPU密集型,内存型数据库
为什么redis在redis-server中是单线程如果采用多线程有什么后果
加锁复杂,不会控制锁的粒度,多个数据类型(string list hash set zset),每个对象有多种数据结构实现,频繁的cpu上下文切换抵消了多线程的优点
单线程的局限:
不能有耗时操作 ,redis需要响应性能
4.单线程为什么这么快
内存数据库&&高效的数据结构
reactor网络模型 io多路复用 非阻塞io
做了哪些优化
耗时阻塞的操作,另起线程处理
异步关闭大文件
异步释放大内存
异步aof刷盘
io多线程等等。。。。。。。。。。。。
三.redis怎么实现分布式锁?有哪些缺陷?
1.分布式锁
高可用的问题,锁是一种资源
获取锁和释放锁必须为一个对象,需要记录持锁的对象
互斥:确保只有一个对象持有
扩展:怎么获知锁释放 ----怎么获知锁释放---非公平锁/公平锁
是否允许同一个对象多次获取锁 ----重入锁/非重入锁
2.redis怎么实现分布式锁
生成唯一标识value(通常用UUID),用于标识本次加锁的请求
使用redis命令尝试加锁
set lock_key value NX PX timeout
lock_key是锁的名字
value是上一步生成的唯一标识符
NX 保证只有key不存在的时候才能加锁
PX timeout 设置锁的过期时间,防止死锁
判断加锁结果
如果返回OK,说明加锁成功,用户获得锁
如果返回nil,说明锁已经被其他用户获取
执行业务逻辑
客户端获得锁后,执行需要保护的临界区代码
释放锁
释放锁时,需要判断当前锁是否是自己加的(即 value 是否一致),防止误删他人锁。通常用 Lua 脚本保证原子性:
if redis.call("get", KEYS[1]) == ARGV[1] thenreturn redis.call("del", KEYS[1]) elsereturn 0 end
这样只有持有锁的客户端才能释放锁。
异常处理
如果客户端在持有锁期间崩溃,锁会因为超时自动释放,避免死锁。
3.redis怎么做到高可用的
主从复制(Replication)
Redis 支持一主多从架构,主节点负责写操作,从节点负责读操作。当主节点数据发生变化时,会自动同步到从节点。这样即使主节点宕机,从节点也能提供数据服务。哨兵模式(Sentinel)
Redis Sentinel 是官方提供的高可用解决方案。它可以自动监控主节点和从节点的状态,当主节点宕机时,Sentinel 会自动将某个从节点提升为新的主节点,并通知客户端更新主节点地址,实现自动故障转移。集群模式(Cluster)
Redis Cluster 支持数据分片和多主节点,每个节点保存部分数据和备份。即使部分节点宕机,集群仍能继续提供服务,提升了可用性和扩展性。总结:
Redis 通过主从复制、哨兵模式和集群模式,实现了高可用和自动故障转移,保证了服务的稳定性和可靠性。