//一下是我在做钉钉开发时存储token的一段代码
public static function corp_access_token()
{
//将jsapi_ticket存入redis
$redis = new Redis();
$redis->connect(self::$redis_config['host']);
$redis->auth(self::$redis_config['auth']);
$key = 'access_token_val'; //要更新信息的缓存KEY
$lockKey = 'lock_'.$key; //设置锁KEY
$lockExpire = 10; //设置锁的有效期为10秒
//获取缓存信息
$jsapi_val = $redis->get($key);
//判断缓存中是否有数据
if(empty($jsapi_val))
{
$status = TRUE;
while ($status)
{
//设置锁值为当前时间戳 + 有效期
$lockValue = time() + $lockExpire;
//setnx:当需要设置的值存在时就会返回一个假,不存在是就会设置值,且返回设置的值;
$lock = $redis->setnx($lockKey,$lockValue);
//下面的判断是关键
//为了防止用户在进入if语句后出现错误,而导致死锁(那么$lock就永远不会过期)
那么需要加一个$redis->get($lockKey) < time() 但是这个时候所有的用户均可以进来,
为了防止这个时候的并发情况出现,那么必须加$redis->getSet($lockKey, $lockValue) < time() 来避免;
getSet是返回key的旧值且设置一个新值
if(!empty($lock) || ($redis->get($lockKey) < time() && $redis->getSet($lockKey, $lockValue) < time() ))
{
$redis->expire($lockKey, $lockExpire);
$params = array(
'corpid' => parent::$config['corpid'],
'corpsecret' => parent::$config['corpsecret'],
);
$result = self::get('gettoken', $params, false);
if (false !== $result) {
$redis->setex($key,6000,$result['access_token']);
return $result['access_token'];
} else {
if($redis->ttl($lockKey)){
$redis->del($lockKey);
}
$status = FALSE;
return false;
}
}else{
sleep(2);//等待2秒后再尝试执行操作防止过多请求
}
}
}else{
return $jsapi_val;
}
}