通过一个字符创的自增自减操作保证原子性,然后根据返回值来获取指定的数据内容
/**
* 领取金额
* @param $coinId
* @param $coinHashInfo
* @return mixed
*/
public function getCoin($coinSn,$coinHashInfo) {
$key = $coinSn.$coinHashInfo['max_num'];
$creatInfo = $this->_redis->get($key);
if ($creatInfo === false) {//没人领取 从0开始第一个领取
$this->_redis->set($key,0);
$location = 0;
} else {
$location = $this->_redis->incr($key);
}
if ($location == $coinHashInfo['max_num']) {//超过最大领取数
ApiException::throwException(ApiException::COIN_NOT_RECEIVE, '', array(__FUNCTION__.' fail'));
}
//获取指定位置的一个元素 从0开始
$res = $this->_redis->zRange('coin_split_list_'.$coinSn,$location,$location,true);
if (empty($res)) {
Core::write( '---message:领取楚币reids没有get到'.',---data:'.json_encode($res),Core::LEVEL_REDIS_ERROR);
ApiException::throwException(ApiException::COIN_GET_FAIL, '', array(__FUNCTION__.' fail'));
}
$value = array_values($res);
$key = array_keys($res);
$split_array = explode('_', $key[0]);
$getInfo = [
'money' => $split_array[1], //抽到的金额
'coin_split_id' => $value[0], //对应的拆分id
];
return $getInfo; //返回抽到的金额
}
问题:上述的get set很容易在高并发的时候出现超发的现象,应该修改成原子操作。
$key = $coinSn.'_create_num';
$location = $this->_redis->decr($key);
if ($location < 0) {
ApiException::throwException(ApiException::COIN_NOT_RECEIVE, '', array(__FUNCTION__.' fail'));
}
$res = $this->_redis->zRange('coin_split_list_'.$coinSn,$location,$location,true);
if (empty($res)) {
Core::write( '---message:领取楚币reids没有get到'.',---data:'.json_encode($res),Core::LEVEL_REDIS_ERROR);
ApiException::throwException(ApiException::COIN_GET_FAIL, '', array(__FUNCTION__.' fail'));
}
通过原子操作decr保证取到的位置唯一,从而获取唯一的数据