用集群处理微信业务,微信的token存放在redis,当长时间没业务过来,token过期后,突然高并发同时请求到集群,不同服务器上的node同时去微信获取token,由于请求微信的返回的不确定性有可能导致最后存到redis的token无效。请问这种情况该如何避免比较好?
单台文件,多台redis
单独的线程(定时器)处理token、别发生业务时才去判断和申请token。不然并发必然会导致问题 From Noder
这是个值得关注的问题,开发了这么久的微信,还一直没有想过,估计是还没遇到高并发的情况。
@i5ting 这个还是没解决token已经过期后突然高并发过来会出现多个请求刷新token的情况
@limaofeng 感觉开个定时器去维护浪费资源
@qinyang912 我也还没遇到,只是刚好想到
@swfbarhr 请问有没事件队列的demo,不太会队列,还有请求需要设置个超时
@i5ting 而且该项目中并没使用微信返回的expires_in减去部分时间作为有效时间,而是直接写死7000秒,这有点不好
mk
缓存token,微信的token过期时间是7200秒,把缓存过期时间设置为7140秒
@zhengnz 如果7200秒内没请求过来,突然在7300秒时多请求并发过来就可能出现问题
@WayneLiang 使用请求队列,标记一下,当前在请求了,让其他请求不实际发生
@WayneLiang 你所说的这种并发导致的错误情况还有可能很多,过期未刷新,或者缓存中并未存在token,却同时有多条处理需要用到token而导致并发发起获取token,或者token已刷新,但已有其他程序获取老token还没执行完,从逻辑上考虑这些问题是很多,所以应该加一个重试的机制,并对于获取token来说,错误的可能也就是token过期或失效,那么只要重试能获取到可用的token即可
考虑到我不同业务不同node但用到同个token,做队列好像也不行,暂时只能标记或锁上,当请求token中,其他需要token的请求统一响应重试
我觉得比较靠谱的做法有:
- 主动定时刷新
- 博客中的第五种方法, 存储 key = (value, 过期时间), 在 redis 中 key 不过期, 代码中检测到过期, 则使用@swfbarhr 提到的 setnx , 过期时间短点, 成功 set 的做这个重新获取数据操作
与其他方法区别在于获取数据操作过程中, 取到是过期值, 而不是空值
@swfbarhr 用的 eventemitter 适用于单进程, 多进程可以使用 redis 的 Pub/Sub
@magicdawn redis pub/sub 不是guaranteed delivery吧
@swfbarhr 的做法比较合理, 需要token时, 去redis取, 如果过期了, 就取一个锁, 取到锁的服务器去微信拿token, 其余的设一个timeout后去redis取, 如果还是没取到, 重复.