目前阻塞队列和异步队列两种方式都有使用,具体选择哪种可根据项目具体情况进行选择,我顺便已经做了优缺点了罗列
阻塞队列
- 生成uuid
- 插入到redis List
- 通过当前的uuid和队列第一条对比是否相等,相等则进行业务处理并弹出队列,否则等待
- 超过等待时间,弹出队列(走异常处理)
优点:代码实现简单,不影响原代码逻辑,在外部嵌套一层即可,可以迅速实现排队处理数据的需求
缺点:会阻塞请求,超时等待时间不能大于nginx超时时间,否则一个超时,后边的全部超时
$result = $this->loadLogic('product_logic')->getLock(array($this, 'editTeamByParams'), array($params)); |
异步队列
- 生成uuid
- 插入到redis List
- 保存请求url、入参到db
- 用php-cli方式从队列中取第一条数据
- 处理后弹出队列
优点:不会阻塞请求,接口响应迅速,适合大量请求处理
缺点:方式不是很简单,需要有一个插入队列的方法,一个处理队列数据的方法,还需要一个队列的消费者,对原代码逻辑有影响
//插入队列 |
生成唯一id的方法
使用redis生成唯一id,保证分布式系统中唯一,参考https://github.com/hebaoxia/generate-uuid /**
* 通过redis生成uuid
*
* @param integer $length
* @return void 2018071900000357
*/
public function getUUID($length = 16){
if (!isset(self::$ci->redis)) {
self::$ci->redis = new Redis();
self::$ci->redis->connect(config_item('ERP_REDIS_HOST'),config_item('ERP_REDIS_PORT'));
if (config_item('ERP_REDIS_PASSWORD')) self::$ci->redis->auth(config_item('ERP_REDIS_PASSWORD')); //密码验证
}
$redis = self::$ci->redis;
$table = 'uuidGenerator';
$today = date('Ymd');
$maxLen = $length - strlen($today);
$counter = $redis->hIncrBy($table, $today, 1);
$counterLen = strlen($counter);
if ($counterLen > $maxLen) {
return false;
}
if ($counter == 1 && $redis->hLen($table) > 7) {
$this->cleanGenerator(7);
}
return $today . str_repeat('0', ($maxLen - $counterLen)) . $counter;
}