摘要
虽然选择php为开发语言,性能就不是其侧重点,但是一些错误代码会严重拖慢整个系统,下列一些错误示例是需要明令禁止的。规范大致方向是减少redis调用次数,合并redis请求,减少时间复杂度。
setKey时
1.setkey时可以顺便将过期时间也设置了,设置string类型时,其他类型时可以,使用事务来解决。
// 实际上调用SETEX命令,10秒过期时间,如果key存在则覆盖
$redis->set('key','value', 10);
// 10秒过期时间,只在键不存在时, 才对键进行设置操作
$redis->set('key', 'value', ['nx', 'ex'=>10]);
// 1000毫秒,只在键已经存在时, 才对键进行设置操作
$redis->set('key', 'value', ['xx', 'px'=>1000]);
//设置hash类型,同时设置过期时间
$redis->multi()
->hMSet($key, $value)
->expire($key, $expire)
->exec();
2.还有像zadd,lpush,sadd支持插入多个元素(Redis>=2.4),从数据库查询出数据后,不要一条一条的插入!
//错误示例
foreach($list as $v) {
$redis->rpush($key, $v);
}
//优化后
$redis->rpush($key, ...$list);
//如果不幸你的php版本小于5.6那么就这样
$params[] = $key;
$params = array_merge($params, $value);
call_user_func_array([$this->redis, 'rPush'], $params);
//call_user_func_array函数是php>=4.0.4,你的php版本不能再低了
将上述两点结合一下,可以在项目里封装一下其他类型的操作,毕竟还是很常见的操作
$result = $redis->multi()
->rPush($key, ...$list)
->expire($key, $expire)
->exec();
getKey时
1.有两个操作经常连在一起,先判断redis里是否存在key,存在则获取,封装一下,使用事务连到一起。当然也可以直接取如果为空则认为没有,但当为string类型且为0时不行。
$result = $redis->multi()
->exists($key)
->zRange($key, 0, -1, true)
->exec();
return $result[0] == false ? false : $result[1];
2.还要注意时间复杂度
//错误示例,时间复杂度: O(log(N)),N 为有序集的基数
$count = $redis->zCount($key, '-inf', '+inf');
//zCard命令,时间复杂度: O(1)
$count = $redis->zCard($key);
3.其他
有个常用的操作就是判断zset里是否有某个元素,使用zRank命令来判断,没有将返回false
public function zIsMember($key, $data)
{
$result = $redis->zRank($key, $data);
return $result === false ? false : true;
}
删除key时
删除key是支持多个key同时删除的,redis在4.0.0之后还支持了非阻塞删除unlink命令
//错误示例
$redis->del($key1);
$redis->del($key2);
$redis->del($key3);
//两种传参方式
$redis->del($key1, $key2, $key3);
$redis->del([$key1, $key2, $key3]);
//两种传参方式
$redis->unlink($key1, $key2, $key3);
$redis->unlink([$key1, $key2, $key3]);
redis集群时需要注意
在redis集群中事务不允许在多个key上操作命令,但当所有key散列到同一哈希槽时便可以。注意,key都在同一个节点上是不够的,必须哈希到完全相同的哈希槽。
对于所有这些多个键命令(mget和mset除外,但这两个命令只能对string类型操作),rediscluster类将验证每个键映射到同一个哈希槽,并发出“交叉槽”警告,如果没有,则返回false
可以使用键哈希标签(Keys hash tags),来保证将key散列到同一个哈希槽。当键包含一个 “{…}” 这样的模式,只有 { 和 } 之间的字符串会被用来做哈希以获取哈希槽。比如操作的键名前缀都相同,我们即可采用此方法。