2021-02-12 15:46:40
在Workerman中集成Redis可通过PHP的Redis扩展实现,主要步骤包括安装扩展、建立连接,并利用Redis实现缓存与消息队列功能。 以下是具体实现方法及关键代码示例:
一、环境准备与连接建立安装Redis扩展通过命令行安装PHP Redis扩展:
pecl install redis安装完成后,在php.ini中添加extension=redis.so并重启PHP服务。
建立Redis连接在Workerman中创建Redis连接对象,示例代码:
$redis = new Redis();$redis->connect('127.0.0.1', 6379); // 默认端口6379// 或使用持久连接(可选)$redis->pconnect('127.0.0.1', 6379);Redis作为缓存层可减少数据库查询,提升响应速度。核心逻辑为:先查缓存,未命中则查询数据库并写入缓存。
基础缓存示例
function getUserData($userId) { $redis = new Redis(); $redis->connect('127.0.0.1', 6379); $key = "user_data:{$userId}"; $data = $redis->get($key); if ($data === false) { // 模拟数据库查询 $data = ['id' => $userId, 'name' => 'Test User']; $redis->setex($key, 3600, json_encode($data)); // 缓存1小时 } else { $data = json_decode($data, true); } return $data;}缓存策略优化
过期时间:根据数据更新频率设置合理过期时间(如setex)。
缓存雪崩:通过随机过期时间(如3600 + rand(0, 600))分散压力。
缓存穿透:对空结果缓存短时间(如set('empty_key', '', 60))。
Redis的发布-订阅模式或列表结构可实现异步任务处理,提升系统并发能力。
发布-订阅模式
发布消息:function publishMessage($channel, $message) { $redis = new Redis(); $redis->connect('127.0.0.1', 6379); $redis->publish($channel, $message);}
订阅消息(需在Workerman Worker中持续监听):$redis = new Redis();$redis->connect('127.0.0.1', 6379);$redis->subscribe(['task_channel'], function ($redis, $channel, $message) { echo "Received task: {$message}n"; // 处理异步任务});
列表结构队列
生产者:$redis->lPush('task_queue', json_encode(['type' => 'email', 'data' => 'test@example.com']));
消费者(阻塞式获取):while (true) { $task = $redis->brPop('task_queue', 10); // 阻塞10秒 if ($task) { $taskData = json_decode($task[1], true); // 处理任务 }}
分布式锁使用Redis的SET NX EX实现分布式锁,避免并发冲突:
function acquireLock($lockKey, $timeout = 10) { $redis = new Redis(); $redis->connect('127.0.0.1', 6379); $lockValue = uniqid(); $result = $redis->set($lockKey, $lockValue, ['NX', 'EX' => $timeout]); return $result ? $lockValue : false;}function releaseLock($lockKey, $lockValue) { $redis = new Redis(); $redis->connect('127.0.0.1', 6379); $script = ' if redis.call("GET", KEYS[1]) == ARGV[1] then return redis.call("DEL", KEYS[1]) else return 0 end '; return $redis->eval($script, [$lockKey, $lockValue], 1) === 1;}性能优化
连接池:使用SwooleCoroutineRedis或第三方连接池库(如RedisPool)减少连接开销。
管道操作:批量执行命令(multi/exec或pipeline)降低网络延迟:$pipeline = $redis->multi(Redis::PIPELINE);$pipeline->set('key1', 'val1');$pipeline->set('key2', 'val2');$pipeline->exec();
数据结构选择:
计数器:使用INCR/DECR。
排行榜:使用有序集合(ZADD/ZREVRANGE)。
连接失败
检查Redis服务是否运行:redis-cli ping(应返回PONG)。
确认防火墙是否放行6379端口。
超时问题
调整连接超时时间:$redis->connect('127.0.0.1', 6379, 2.5);(2.5秒超时)。
优化网络环境,避免跨机房访问。
数据一致性
使用事务(MULTI/EXEC)或Lua脚本保证原子性:$redis->eval('redis.call("SET", KEYS[1], ARGV[1]); redis.call("EXPIRE", KEYS[1], ARGV[2])', ['my_key', 'my_value', 3600], 1);
通过合理利用Redis的缓存与消息队列功能,Workerman可轻松应对高并发场景,显著提升系统性能与可扩展性。