一、背景介绍
1.问题简介
本次问题是由OAuth 2.0
授权框架(用于授权第三方应用程序【客户端】访问受保护的资源。)存储在Redis
集群中的一个key引起的:client_id_to_access
(或称为 “client ID to access”)通常是指在OAuth 2.0
认证流程中,客户端(Client)使用的唯一标识符。导致溢出原因:当使用命名空间存储client_id_to_access
和uname_to_access
的列表数据时,整个键的过期时间会随列表数据的更新而刷新。这可能导致与同一clientId
或username
相关的令牌过期后,键却没有被及时删除,从而导致内存溢出问题。简单来说TTL
过期时间一直处于被无限重置状态从而是数据变成了变相的永久存储导致Redis
内存溢出。
2.Redis相关信息
Redis
采取的是三主三从集群模式,部署在k8s上采取了固定集群ip池的方案。集群详细信息如图:
二、发现&解决
1.发现
根据监控观察redis近1个月的内存使用情况如图:
可以看到Redis内存稳步增长至100%导致内存溢出系统崩溃
使用工具进行 内存分析 研究:
从图中看出client_id_to_access大小已经达到了1GB存储的个数也是上升到了近8W之多!
2.解决
修改Redis配置文件增加配置 notify-keyspace-events Ex,使其永久生效
连接服务端输入命令:config set notify-keyspace-events Ex,使其即刻生效
介绍:
Redis的notify-keyspace-events选项的 Ex参数:
该选项启用了对键过期事件的通知,使你能够在键过期时执行相应的操作。
然后,在你的应用程序中,订阅Redis的键过期事件通知。你可以使用Redis的客户端库(如Jedis或Lettuce)订阅过期事件,并在事件触发时执行相应的操作,例如删除与过期键相关的数据或执行其他清理操作。
Jedis jedis = new Jedis("localhost");
JedisPubSub jedisPubSub = new JedisPubSub() {
@Override
public void onPMessage(String pattern, String channel, String message) {
// 在这里处理过期键的事件
System.out.println("键过期:" + message);
// 执行相应的操作,如删除与过期键相关的数据
// jedis.del("your_key");
}
};
// 订阅过期事件,通配符匹配以 "__keyevent@*__:expired" 结尾的键
jedis.psubscribe(jedisPubSub, "__keyevent@*__:expired");
3.检验
三、结束语
本次关于Redis
因OAuth 2.0
内存溢出解决方案就到此结束了,后期会给大家带来更多的脚本,感谢认真读完,如果觉得还可以,那么给作者点赞、收藏、关注吧!