请教一个问题,多实例同时删除 key 怎么解决

2019-10-14 10:27:39 +08:00
 UserNameisNull

背景:redis放了微信的access_token,缓存时间是expire_time - 200s,当有新的token生成,旧的就会失效。

服务有多个实例,取到access_token后请求微信接口,微信接口报token失效的错误,就从redis中删除 key 并更新为最新的。

就会遇到 A 实例拿到一个token,B 实例把token更新了,就会导致 A 实例报错。

有大佬可以提供一个思路吗?

3172 次点击
所在节点    程序员
35 条回复
hero2040407
2019-10-14 15:05:08 +08:00
不是每次请求都去重新拿一次?那就每个实例都在固定时间来更新 access_token
lihongjie0209
2019-10-14 15:06:58 +08:00
最简单的就是中控服务器, 其他的方案都有问题, 要不实现困难, 要不无法保证正确性
UserNameisNull
2019-10-14 15:13:48 +08:00
中控服务器肯定是单实例,无法做到高可用,怎么办呢?
单实例怎么情况下 重新部署 或者 重新发布 就会导致服务中断,或者两个实例并存一段时间。
b821025551b
2019-10-14 15:17:49 +08:00
@WuMingyu #15 你这边共存有什么用,微信那里只有一个是有效的。
UserNameisNull
2019-10-14 15:21:15 +08:00
@b821025551b
微信文档说了 https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/access-token/auth.getAccessToken.html,新的出来,老的还能用 5 分钟。
问题是 有 A,B,C 三个服务,同时更新,必然有个服务的 Token 是失效的。
b821025551b
2019-10-14 15:25:06 +08:00
@UserNameisNull #25 这是对你这边对开发对建议,并不是微信那边的机制,token 就是只能有一个是有效的
killergun
2019-10-14 16:04:17 +08:00
access_token 推荐有固定服务去刷新,刷新之后旧的 access_token 在几分钟内还是有效的,这样就不会有问题了
b821025551b
2019-10-14 17:05:37 +08:00
@UserNameisNull #25 刚摸鱼差点被发现,重新说:
文档里提到的这个 5 分钟,是给你这边开发的建议,建议去保留这 5 分钟;而微信的 token 机制压根不存在这 5 分钟,新的出来,老的必定失效,不存在什么并存的。
leegoo
2019-10-14 20:53:15 +08:00
@b821025551b 以前我开发过,好像并不会直接失效,有一个平滑过渡时间
liukangxu
2019-10-14 21:08:36 +08:00
白纸黑字的官方文档不相信,还能怎么办呢,无非是浪费自己和他人的时间罢了
lianyue
2019-10-14 21:22:03 +08:00
其实啊 加个重试就好了 因为 就算没刷新 access_token 也可能用户取消授权 导致失效

1. 读取数据库 的 access_token 判断 (是否需要刷新)刷新失败就 出错并结束 成功就储存到数据库
2. 请求微信的 api
3. 如果提示 access_token 失效了就再读取下数据库 如果 再读取的 access_token 和 老的 access_token 相同 就 出错并结束
useben
2019-10-14 23:08:30 +08:00
最简单,最稳的方案:redis 集群存 access_token,lvs+多实例专门负责请求刷新 access_token 和提供获取 access_token 接口,其他的请求接口就行了。
conn4575
2019-10-15 08:33:11 +08:00
5 楼正解,所有要求全局统一的 token,包括 session 都应该使用中控服务的思想,redis 只是存储层的事情
Kerwin1202
2019-10-15 09:00:01 +08:00
赞同 5 楼,几台机器,专门用一台机器一个站点刷新 token 的
Ianchen
2019-10-15 09:14:02 +08:00
赞同 5 楼的做法. 实际还是分布式问题, 如果想避免, 则考虑下刷新 access token 的工作给开一个队列消息, 然后无论是 zk, kafka, rabbitmq 等, 都会自己寻找一个可用有效的节点去刷新. 有时候可以用消息队列来规避掉分布式的问题

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/609041

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX