分布式令牌的发放与回收
作者:互联网
一、概述
首先说一下使用场景,在分布式环境中,想要控制令牌的发放数量,并且还需要将用完的令牌回收回来,可以理解为 Java 中 Semaphore 类的分布式实现。
二、技术实现
借助于 Redis,依赖于 Redis 对客户端命令进行串行执行的特性来保证功能的实现。
实现思路,以下是针对于单个 token 的,当然多个 token 是可以并行的。
1、获取分布式锁
2、修改数据
3、释放分布式锁
这个分布式锁是支持自动续期的,但是这个修改数据的步骤很快,一般也不会发生自动续期,为了兜底,加上了自动续期。
数据结构的定义
首先定义一个 redis key:token:manager
,它的数据结构是 Set,里面存储的是各种 token 的值,比如一个 token 是负责接口限流,那么这个 token 的值可以定义为 token:api_limit
,然后存储在 token:manager
中。
接下来,怎么去知道这个 token 被发放了多少次令牌数呢?
可以以这个 token 的值作为 redis 的 key,接着上面说的这个 key 就是token:api_limit
,它的数据结构也是 Set,里面存什么呢?里面存储令牌持有者的信息,这就产生一个要求,在分布式环境下,令牌持有者的标识必须是唯一的。
此时,可以通过计算 Set 结构中元素的数量,得出这个 token 已经发放了多少次令牌。
如果令牌发放出去了,持有令牌的线程挂了,没来记得将令牌还回来怎么办呢?
需要为令牌设置一个自动过期时间,由于加入了自动过期时间,又会导致业务逻辑没执行完令牌被过期了,导致出现令牌超发的问题,还需要加入令牌自动续期机制,可见为了更好用,系统是更复杂的。
自动过期怎么做呢?
用一个普通的字符串类型进行存储上面token:api_limit
内的令牌持有者信息,比如:token:api_limit@val@thread-1
,然后对这个 key 设置自动过期时间。
此时还要考虑一个问题,就是这个字符串类型的 key 如何与上面 Set 结构里的元素进行联动呢?
在业务代码中加入一个定时任务,定时扫描这些 key,如果过期了,就去 Set 集合里操作删除即可。
用图表示如下:
代码地址:吴庆龙/redis-token (gitee.com)
标签:令牌,Set,过期,回收,token,key,分布式 来源: https://www.cnblogs.com/wuqinglong/p/16512179.html