当我们把 Redis 当做缓存来使用时,设置过期时间是必须的,但具体设置多少的过期时间呢,针对不同的场景会有不同的决策。
虚假一个场景,我们基于用户的地理位置推荐附近的陌生主播,用户可以线下去找主播沟通。当系统第一次匹配出最佳主播时,我们缓存主播的地理位置。在一段时间和地理范围内,这个推荐的结果保持不变。
我们可以从二维坐标系下手,时间和距离分别是xy轴,原点假设是用户的当前位置,用户移动的过程就可以用图中的①、②、③清晰的表示出来。这种坐标轴的思考方式也算的上是结构化思维了,能够让我们更清晰地理解问题。
缓存 Key 的设计也有很多处理思路,假设每个用户存储单个key,过期时间设置10分钟。我们只有第一次创建缓存的时候设置一次缓存过期时间,在缓存没有过期的时间范围内,我们对缓存可以进行数据更新,但不更新它的过期时间。
这样的处理会有一个风险,主要根因是缓存的key是同一样。如果在某一次创建 key 成功,设置缓存过期时间失败的话,缓存可能会持续 20 min。
解决这个问题的思路也特别简单:时间分片,在构造缓存 key 的时候加入时间片的信息,直接每10min一个时间片。熟悉过服务限流会有体会,两边的原理其实是一样的。
获取当前时间秒除以 600s 就是我们这个时间片的后缀。Go语言中的秒是基于 January 1, 1970 UTC 计算的时间,正好是一天的开始。计算的效果就如下所示:
suffix := time.Now().Unix()/600
fmt.Printf("uid:%d\n",suffix)