第11课:批量操作

Redis的使用使系统压力大幅降低,同时响应速度也很快,但是随着业务的增加,慢慢发现有些情况下,redis速度变慢了,时不时的会抽风
然后就想到要优化,redis的瓶颈主要在于单线程,可能导致多个操作的阻塞,如果我们尽量把可以批量执行的操作一起打包执行,尽量减少redis的资源消耗,那再好不过了
幸运的是,redis提供了这样的功能

批量操作的实现机制主要是利用redis的事务
主要用到命令multi与exec
MULTI标记一个事务块的开始。事务块内的多条命令会按照先后顺序被放进一个队列当中,最后由 EXEC 命令原子性(atomic)地执行
如果开启AOF机制,那么multi和exec的之间的命令也会用一条write命令写到硬盘。如果在写时被硬中断(停电或管理员强制kill),Redis重启时会检测到错误,可以用redis-check-aof工具修复
举例:
multi
操作1
操作2
操作3
exec

以PHP为例
$redis->multi(Redis::PIPELINE);
$redis->操作1($k, $m);
$redis->操作2($k, $m);
$redis->exec();

进一步封装:
public function multiExec() {
	$args = func_get_args();

	$func = array_shift($args);
	$var  = array_shift($args);
	$num  = $this->multi_exec_times;

	$this->is_piping = true;
	$ret = array();

	if (is_callable($func))
	{
	    $redis = $this->multi(Redis::PIPELINE);
	    $var = (array)$var;
	    $var_ct = count($var);
	    $last_exec = true;
	    foreach ($var as $n => $item)
	    {
		$params = array_merge(array($item), $args, array($redis, $n));

		call_user_func_array($func, $params);
		if (($n + 1) % $num == 0)
		{
		    $last_exec = false;
		    $ret = array_merge($ret, $this->exec());
		    if ($n != ($var_ct - 1))
		    {
			$redis = $this->multi(Redis::PIPELINE);
			$last_exec = true;
		    }
		}
	    }
	    if ($last_exec)
	    {
		$ret = array_merge($ret, $this->exec());
	    }

	    return $ret;
	}
	else
	{
	    return false;
	}
}