常见编程问题及对策

2,474 views

Published on

虎扑常见编程问题集及其对策

Published in: Education, Technology, Business
0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
2,474
On SlideShare
0
From Embeds
0
Number of Embeds
588
Actions
Shares
0
Downloads
13
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide

常见编程问题及对策

  1. 1. 常见编程问题及对策<br />——编码失误、并发竞争、雪崩<br />
  2. 2. 我们的目标是<br />没有蛀牙 (defects)<br />大并发、低延迟<br />多 Web server<br />多 Mysql M/S Replication<br />缓存技术<br />NoSQL存贮<br />
  3. 3. 案例研究<br />
  4. 4. 大家来找茬 I<br />[大家来找茬 I]<br />-------------------------------<br />$hitsKey = "hitsKey:$artid";<br />$hitsWriteKey = "hitsTimestamp:$artid"; <br />$currentTime = time(); <br />$num = $tt->get($hitsKey);<br />$lastWriteTime = $tt->get($hitsWriteKey);<br />if (!$lastWriteTime)<br />{<br /> $lastWriteTime = $currentTime;<br /> $tt->put($hitsWriteKey, $lastWriteTime);<br />}<br />$num++;<br />
  5. 5. 大家来找茬 I<br />// [-MASKED-]<br />if (($currentTime - $lastWriteTime) > 1800)<br />{<br /> $sql = 'UPDATE tbl1 SET hits='. $num. ' WHERE aid = '. $artid;<br /> $db->exec($sql);<br /> $tt->put($hitsWriteKey, $lastWriteTime);<br />}<br />$tt->put($hitsKey, $num);<br />
  6. 6. 大家来找茬 II<br />[大家来找茬II]<br />-------------------------------<br />//[-MASKED-]<br />if (getgpc('-MASKED-') == $cache->get('-MASKED-'.getgpc('id'))) {<br />exit('1');<br />} elseif($var = $Model->foo(getgpc('id'), getgpc('-MASKED-'))) {<br />exit('1');<br />} else {<br />exit('-2');<br />}<br />
  7. 7. 编码失误<br />[大家来找茬I]<br />未正确更新缓存时间戳<br />[大家来找茬II]<br />未正确更新缓存 -MASKED- 值<br />新版 GoalHi中也出现一次失误<br />从缓存中取数据却未使用,仍从数据库中再次读取<br />
  8. 8. 编码失误: 对策<br />单元测试<br />脚本化自己的测试<br />功能测试<br />回归测试<br />Xhprof<br />多执行几次,比较执行时间<br />启、禁用缓存条件下的执行时间<br />
  9. 9. 缓存雪崩 I<br />[大家来找茬I]<br />缓存时间戳放置得太晚, 并发量大时会雪崩<br />
  10. 10. 缓存雪崩 I: 对策<br />[大家来找茬I]<br />尽量早地写入, Renew<br />
  11. 11. 竞争条件<br />[大家来找茬I]<br />点击量写入太晚,并发量大时会出现竞争<br />
  12. 12. 竞争条件: 对策<br />如果可以,使用 incr/decr/incrby/decrby<br />原子操作<br />Redis/TT/Memcache都支持<br />否则:<br />乐观锁<br />适用场景<br />悲观锁<br />适用场景<br />否则:<br />读取后,尽快修改并写入<br />
  13. 13. 大家来找茬 III<br />[大家来找茬 III]<br />------------------------------- <br />$count1Id = 'count_1';<br />if (! $count1= $cache->load ( $count1Id )) {<br /> $count1 = $model->foo1();<br /> $cache->save ( $count1, $count1Id );<br />}<br />$count2Id= 'count_2';<br />if (! $count2 = $cache->load ( $count2Id )) {<br /> $count2 = $model->foo2();<br /> $cache->save ( $count2, $count2Id );<br />}<br />$count3Id= 'count_3';<br />if (! $count3 = $cache->load ( $count3Id )) {<br /> $count3 = $model->foo3();<br /> $cache->save ( $count3, $count3Id );<br />}<br />…<br />
  14. 14. 编码失误<br />[大家来找茬 III]<br />缓存时间因失误都为 3600s,导致很多缓存项同时过期,引发冲击<br />
  15. 15. 缓存雪崩 II<br />[大家来找茬 III]<br />并发访问大时,大量缓存项的同时失效<br />超级雪崩<br />
  16. 16. 缓存雪崩 II: 对策<br />GetOrLock延迟过期<br />延期删除<br />
  17. 17. 缓存雪崩 II: GetOrLock<br />服务器端方案<br />Cons:<br />Fork 代码,增加维护成本<br />请大家务必不要 Fork 上游代码<br />Zend Framework<br />Hoop Framework<br />封装优于补丁<br />客户端方案<br />感谢 鹏鹏、亮亮 (排名不分先后)<br />Pros<br />Cons<br />
  18. 18. 缓存雪崩 II: 延期删除<br />步行街<br />频繁更新<br />Memcache<br />DELETE 改进<br />Redis<br />EXPIRE<br />
  19. 19. 往返延迟<br />[大家来找茬 III]<br />单个单个地从缓存中取值,往返性能低<br />
  20. 20. 往返延迟: 对策<br />Multi GET,避免往返时延<br />
  21. 21. 其他问题<br />
  22. 22. 文件缓存<br />GoalHi项目<br />新人未经培训,采用文件缓存技术<br />
  23. 23. 为什么文件缓存是个坏主意?<br />分布式环境<br />NFS 性能偏低<br />
  24. 24. 重复代码<br />每个项目都有自己的一套“框架”拷贝<br />Zend Framework<br />全站脚本、CSS<br />部署/升级麻烦<br />一致性问题<br />
  25. 25. 重复代码: 对策<br />Photo 项目案例:<br />Zend Framework 作为一个公共库<br />/path/to/zend/Zend<br />已在 include path 中,可以直接包含<br />Hoop Framework<br />作为一个公共库部署<br />新人入职培训<br />让新人符合 Hoop 编程习惯<br />
  26. 26. 长连接、持久连接<br />多服务器多进程环境下<br />通常立刻带来问题<br />大量的连接挂在 Server 上<br />10 * 500 = 5000 连接<br />对于多线程服务器是灾难<br />保持 5000 个线程环境,以及其它资源<br />对于事件驱动的服务器也会影响性能<br />同时 e/poll 大量的连接<br />TCP 连接本身在内核亦会占用非分页内存<br />
  27. 27. 长连接、持久连接: 对策<br />短连接<br />使用时连接,用完立即关闭<br />连接池<br />编码仍按”短连接”方式<br />SqlRelay<br />RedisProxy<br />
  28. 28. 谢谢!<br />

×