php optimization for millions visits level
TRANSCRIPT
千万级 PHP 接口优化kim
问题• 什么是千万级?• 接口扛不住,措施 1 、 2 、 3 是?• 如何优化?
并发数• 10000000 / 86400 ≈ 116
• 按高峰期 10 倍,即 1160req/s
观察• Ping • Trace• HttpWatch• Uptime• Top• Free• Nagios
Top 举例
紧急措施• 重启• 缓存穿透• 启用备机(如果有的话)
系统日志• Nginx access log
• Nginx error log
• PHP error log
• PHP slow log
访问统计• 各种访问统计• awk -F"[" '{ print $1 }'
/home/nginx/logs/access.log | sort | uniq -c | sort -rn | head -n 10
非 200 统计• 非 200 访问• cat /home/nginx/logs/access.log | grep -v
"\"200\""
日志统计系统• https://56.com/ops/index.htm
PHP 慢?• 有 opcode cache 的 PHP ,已经够快了!
真正的原因• 端口( Socket )连接慢• 端口( Socket )数据交互多
举例 1
• mysql_connect() • mysql_query()
• redis->connect()• redis->select()
举例 2
• memcache->connect()• memcache->get()
• new Mongo()• MongoCollection->find()
举例 3
• Http::Get()
如何优化 Socket
释放要主动• mysql_close()• Redis->close()• Memcache->close()• Mongo->close()• unset
验证要提前• 比如: xxx.56.com/api/someapi.php :• <?php• if (!isset($_GET['ids'])) {• die('Invalid arguments');• }• require 'index.php';
缓存要耦合• 评论数• 人气• 视频顶踩
如何优化 PHP
PHP 优化利器• http://pecl.php.net/package/xhprof
XHProf 安装• XHProf lib 包• 代码举例
XHProf 举例
代码“完美”了,还能优化吗?
Tcp 短连接也不能忍受了!
特性• 1. 轻量,安装配置简单• 2. 多点长连接• 3. 自动冗余• 4. 支持 memcached ascii 和 redis 协议• 5. 可监控,可记录日志
站内使用状况• Infov 视频信息接口• Stat 人气接口• Album 专辑信息接口
客户端选择• Memcached (推荐) VS Memcache
• Phpredis (推荐) VS Predis
反复实战• Memp 类使用举例• $mm = new Memp(array('servers' =>
array('127.0.0.1', 22122)));
Twemproxy 日志• -v, --verbosity=N set logging level (default: 5, min: 0, max:
11)
• 日志举例
Twemproxy 的问题
Memcache 删除不了• Bug 如下:• command_len = spprintf(&command, 0,
"delete %s %d", key, time);• command[command_len] = '\0';
• 需要人工修复:• command_len = spprintf(&command, 0,
"delete %s", key);
乱码与截断• 不能压缩• Memcached->setOption( Memcached::OPT_COMPRESSION,
false);
EOF
• Twemproxy 要求 EOL 是 “ \r\n” ,而不是 “ \n” ,所以在一些情况下是要注意,比如使用 nc 时,要带上 -C 参数,但不是每个版本的 nc 都带这个参数
• $ echo get key | nc -C 127.0.0.1 22121
配置要接地气• 痛苦的经历:不支持 redis->select()
保正一致性• hash: md5• distribution: ketama
缓存冗余• auto_eject_hosts: true
• 无规律• 不一致
如何清缓存?• 循环删除 + 队列补刀• Infov 代码举例
总结
毫秒必争• 如过你的接口平均服务时间是 30ms ,那么
1ms 的价值就是 3% 的性能提升!
• 提升 1ms 的途径:• 1. 把 count 移出 for 循环• 2. 把 preg_match 换成了 strstr• 3. 去掉了数组的 交集 / 并集 / 合并 操作• 4. 少创建了几个 memcache 对象
• 实践和测试• 加节点是最后手段
谢谢!