discuz论坛sessions表最终优化方案

作者 : admin 于 2010年01月17日, 23:00:29
2010
01-17

最近一直在折腾dz的sessions表优化。经过某群好友的各种方法提示和一些高数据量用户论坛的鼎力支持,总结以下优化方案。部分方案是在某些论坛正在使用的,部分方案是我发散思维总结的,没有经过大数据量和大负载下的应用,只是作为一个备选的方案,当然欢迎朋友们拿去实践。

1、分库

这个方法至少两三个注册用户百万级至千万级的论坛在使用。实施也比较简单,只需要把sessions表放在其他的库中,跟论坛主库分离,这样,就可以用多台服务器来分担论坛压力。sessions表查询的地方,如果直接查询,则连sessions表所在的库,如果是联查,则分别查询后,合并插叙结果。

2、砍功能

这个方法虽然不实用,但的确有效。仔细看看dz的一些sql语句,就知道砍掉某些功能摆脱sessions表的约束,性能会有多大的提高。砍功能,最终还是为了提升性能。但如果不砍功能又提升性能,才是终极目的。此方法适用于对某些统计功能要求不高的论坛使用。

3、memcached存储sessions,异步统计用户的在线数据

此方法其实还是砍掉了论坛的用户在线统计功能而独立开发一套统计系统。此思路来源于我们的统计服务器。如果统计服务器已经统计了部分信息,就没必要再去耗费大量的sql效率去进行统计。当时我们负责统计的吴同学正好也要开发一套针对不同系统的统计代码,我可以直接把要统计的数据提交给统计服务器,再由统计服务器返回统计结果。以异步的方式来统计,化解dz sessions表的性能瓶颈。而统计信息的异步提交,可以提交到本地数据库,可以提交到第三方统计系统,当然也可以根据需要独立开发一套小型统计系统。

方案3是本人原创方案,方案的修改代码在以下附件中: 异步session统计信息同步,欢迎大家使用。

由于dz的开发考虑的是大众市场,功能冗余代码逻辑复杂。但优化dz并不是那么的困难,而优化的思路,也是跟其他系统优化相似:mysql瓶颈。一个即将崩溃的系统,或者频繁崩溃的系统,是进行优化的最好示例:减少sql查询,提高sql语句查询效率。dz考虑大众市场,为了提高产品兼容性,并没有引入太多的第三方软件:比如memcached,bdb,ttserver等,虽然内部已经为主从预留了接口,但未见很明显的文档支持。
第三个方案优化的思路也很明显,减少sessions表的慢查询而改为memcached高速的数据存储,把统计功能做接口留出,此功能给第三方来做。这样sessions表的瓶颈即可消除。

使用无模式数据库来改造dz的session

作者 : admin 于 2009年12月29日, 09:26:58
2009
12-29

前两天还不知道啥是无模式数据库,不过最近迫切需要修改discuz bbs的session表,所以研究了一下相关的资料,发现了无模式这个名字。

具体无模式是啥,这里找了两篇文章:

关系数据库的末日是否已经来临
关系数据库的根本问题分析及数据库革命之走向

关于无模式的应用案例,很典型的一个,就是康盛uchome的feed表。

这里简单介绍几个无模式数据库,供大家参考:

mongodb : http://www.mongodb.org/display/DOCS/Home

mongodb的php扩展 http://www.mongodb.org/display/DOCS/Installing+the+PHP+Driver#InstallingthePHPDriver-PECL

这个数据库已经在淘宝上配合10gen做了云计算的session(名字很操蛋),具体资料在这里 http://rdc.taobao.com/blog/dw/archives/410。具有了实际应用的东西应该很不错,不过我没尝试过。

Tokyo Tyrant:http://1978th.net/

tt的php扩展 http://www.php.net/manual/en/book.tokyo-tyrant.php

这个大家就比较熟悉了,SB日本鬼子写的东西,应用很广,sina,qq等公司里都在大量应用,sina的研发团队在此基础上还做了个分布式的东东,很是不错。据说这玩意还得到了很多公司的赞助,shit。

TCSQL:张宴基于tt开发的一套东西,内部做了很多算法优化,具体可参考此文章 http://blog.s135.com/tcsql/

总结:康盛使用mysql来存储session,不能说是一种错,但对于dz的负载绝对是第一个瓶颈。用这种方式,在线人数5w对数据库绝对是个坎。很多负载比较大的论坛,都做了此方面的优化,比如,给session表单独一个数据库,或者干脆阉割此功能。不错,独立的session表,或者分库,访问量大的时候,瓶颈依然在mysql上;阉割此功能,有些心疼,而且很多运营数据会丢失。所以,保持原功能而平滑提升性能,是一个不错的解决方向。

康盛,这么做是不是有点过火了

作者 : admin 于 2009年12月10日, 01:02:25
2009
12-10

使用开源产品,的确能加快我们的产品实现进度,我们也感谢那些提供免费开源产品的人。当然,我个人也喜欢开源技术。

但如果开源的产品中给你下个后门,抓取你的数据,你还能高兴么?

现在分析 discuz 7.0 的几段代码:

  1. if($adminid == 1 && $action == 'home') {
  2. echo '<sc '.'ript language="Jav'.'aScript" src="ht'.'tp:/'.'/cus'.'tome'.'r.disc'.'uz.n'.'et/n'.'ews'.'.p'.'hp?'.bbsinformation().'">';
  3. //echo '</sc><sc '.'ript language="Jav'.'aScript" src="http://localhost/com/n'.'ews'.'.p'.'hp?'.bbsinformation().'">';
  4. }
  5. </sc>

恩,看见了没,我告诉大家一个写木马常用的方式 eval ,比如asp中查找木马,通常查找fso等关键字,木马一般都给他写成 eval(’f'+’s’,'o’),写php的应该很熟悉这个函数了。这段代码当然不是木马,咱看看他具体做了什么:

  1. function bbsinformation() {
  2.  
  3. global $db, $timestamp, $tablepre, $charset, $bbname, $_SERVER, $siteuniqueid, $save_mastermobile, $msn;
  4. $update = array('uniqueid' => $siteuniqueid, 'version' => DISCUZ_VERSION, 'release' => DISCUZ_RELEASE, 'php' => PHP_VERSION, 'mysql' => $db->version(), 'charset' => $charset, 'bbname' => $bbname, 'mastermobile' => $save_mastermobile);
  5.  
  6. $updatetime = @filemtime(DISCUZ_ROOT.'./forumdata/updatetime.lock');
  7. if(empty($updatetime) || ($timestamp - $updatetime > 3600 * 4)) {
  8. @touch(DISCUZ_ROOT.'./forumdata/updatetime.lock');
  9. $update['members'] = $db->result_first("SELECT COUNT(*) FROM {$tablepre}members");
  10. $update['threads'] = $db->result_first("SELECT COUNT(*) FROM {$tablepre}threads");
  11. $update['posts'] = $db->result_first("SELECT COUNT(*) FROM {$tablepre}posts");
  12. $query = $db->query("SELECT special, count(*) AS spcount FROM {$tablepre}threads GROUP BY special");
  13. while($thread = $db->fetch_array($query)) {
  14. $thread['special'] = intval($thread['special']);
  15. $update['spt_'.$thread['special']] = $thread['spcount'];
  16. }
  17. if($msn['on'] && $msn['domain']) {
  18. $update['msn_domain'] = $msn['domain'];
  19. }
  20. }
  21.  
  22. $data = '';
  23. foreach($update as $key => $value) {
  24. $data .= $key.'='.rawurlencode($value).'&';
  25. }
  26. return 'update='.rawurlencode(base64_encode($data)).'&md5hash='.substr(md5($_SERVER['HTTP_USER_AGENT'].implode('', $update).$timestamp), 8, 8).'&timestamp='.$timestamp;
  27. }

看见了吧,看他提交的几个关键字段:$update['members'],$update['threads'],$update['posts'],$thread['special'],$update['spt_'.$thread['special']],$update['msn_domain'],这些字段提交过去,也许对我们系统安全并无影响,可看看6.0版本的论坛还提交了什么:

uniqueid=**&version=6.0.0&release=20081117&php=5.2.6&mysql=5.0.22&charset=utf-8&bbname=**&mastermobile=****&members=4965&threads=883&posts=25921&spt_0=879&spt_1=4&

mastermobile 看见这个字段你会汗不?

康盛应该为此行为买单不?不会 。

看下边:

III 有限担保和免责声明
1. 本软件及所附带的文件是作为不提供任何明确的或隐含的赔偿或担保的形式提供的。
2. 用户出于自愿而使用本软件,您必须了解使用本软件的风险,在尚未购买产品技术服务之前,我们不承诺提供任何形式的技术支持、使用担保,也不承担任何因使用本软件而产生问题的相关责任。
3. 康盛创想(北京)科技有限公司不对使用本软件构建的论坛中的文章或信息承担责任。

您必须了解使用本软件的风险–用户了解信息泄露的风险么?
康盛创想(北京)科技有限公司不对使用本软件构建的论坛中的文章或信息承担责任。其实,我也不愿意承担。

本文纯属月经文,如有难受,过几天自然恢复。