由于用户不断增加,业务功能不断积累,redis的使用也变的越多,单机扩展内存已不是最优解,采用了升级redis集群的方案。
redis集群兼容说明
1.keys 命令不再允许使用,可改用基于游标的迭代器来完成 scan,最后我会列举使用示例。
2.exists 命令也不再允许使用,可通过ttl判断时间来替代,时间复杂度为O(1),或者根据hash,set等类型长度来替代。
3.multi事务中,需要增加watch。这也暗藏着一个bug。
主要修改的是这三个命令。
class pro { public function output($str = '') { echo $str . PHP_EOL; return true; } public function formatList($data) { $data = explode(PHP_EOL, $data); $list = []; $cursor = 0; foreach ($data as $item) { if (empty($item)) continue; if (!$cursor) { $cursor = $item; //没有值,第一个是游标值 } else { $list[] = $item; } } return [$cursor, $list]; } public function main() { $config = config::get('redis_api'); //获取配置 $host = $config[0]['host']; $pwd = $config[0]['pwd']; $port = $config[0]['port']; sleep(2); $redis = new Redis(); //实例化redis $cursor = 0; //游标值,为0表示结束 $size = 100; try { do { //命令行方式执行redis scan $shell = "redis-cli -h $host -a $pwd -p $port scan $cursor match " . $this->redisKey . "* count $size"; $result = shell_exec($shell); //格式化游标和内容 list($cursor, $list) = $this->formatList($result); foreach ($list as $key) { //进行对结果的操作,如下删除key $redis->del($key); } } while ($cursor != 0); } catch (Exception $e) { $this->output('error:' . $e->getMessage()); } } } $pro = new pro(); $pro->main();
$redis = new redis(); $key = 'test_zp'; //升级集群增加的watch $redis->watch($key); //实例化事务 $multi = $redis->multi(Redis::PIPELINE); //批量执行插入操作 foreach ($list as $item) { $redis->ZADD($key, time(), $item . random_int(100, 500)); } $multi->exec(); // 重点,因为集群升级所加的watch必须用unwatch配合使用 // unwatch必须加 $redis->unwatch($key);
Redis::PIPELINE是为了管道方式执行为了避免多次链接,一次请求完成多个操作。
由于使用了管道,导致了必须使用unwatch,不然会导致exec后面的redis操作失败。