[原创]Discuz! BBS缓存整体方案

[ 文章作者:陈臻 本文版本:v1.0 最后修改:2009.6.22 转载请注明原文链接:http://www.54chen.com/c/611 ]

DZ的缓存方案是经典之作,不论是系统的主动缓存还是帖子内容的被动缓存。在我前面的博文【[原创]Discuz! BBS的主动缓存和被动缓存】里所讲述的是DZ的缓存常用的一种方法,下面再说在DZ系统里如何决定一个内容是不是要缓存。

所有的数据全都缓存,不失为一个好办法。但是,在数据更新要求及时的环境下,例如帖子回复的内容要求立即显示等地,又不得不对其缓存进行更新。所以,基本上每一个成熟的系统,都不会去把所有的东西缓存起来。这时是不是让各位很困惑,缓存就是一把双刃剑,用好了系统效率事半功倍,用得不好,产品功能将受到严重影响。DZ就是一个缓存与不缓存选取得当的系统。

我们一起进入DZviewthread.php,也就是负责显示帖子内容的一个文件。代码一开始有这样一个判断:

$page = max($page, 1);

if($cachethreadlife && $forum['threadcaches'] && !$discuz_uid && $page == 1 && !$forum['special']) {

       viewthread_loadcache();

}

这是什么意思呢?基本上就是在说,当一些系统的设置都满足的时候,只要是第一页就去执行viewthread_loadcache(),各位已经等不及看这个函数的意思了吧,且慢,先说说为什么选中了第一页。在经过大家长期的总结下,发现一个成熟论坛大多数时间会员都会停留在帖子的第一页,所以,DZ大胆地只将第一页进行缓存。

DZ真的是只将第一页进行缓存吗?答案是否定的,下面我们来看viewthread_loadcache()这个函数里的内容。

这个函数写在了viewthread.php538行,看到这个函数的第一感觉,是专业。DZ的多年开发,已经将论坛的行为研究深深刻在了代码里。如下这段代码,这个函数里的$threadcachemark这个变量,被定义为与帖子的显示顺序、是否加精、此版最后回复天数、帖子浏览数、回复数、每页显示条数进行运算得到的一个值,如果这个值小于了版块的设置,这个帖子的内容才会生效。就也是说,DZ甚至还不是但凡第一页就缓存!

$threadcachemark = 100 - (

              $forum['displayorder'] * 15 +

              $forum['digest'] * 10 +

              min($forum['views'] / max($forum['livedays'], 10) * 2, 50) +

              max(-10, (15 - $forum['lastpostdays'])) +

              min($forum['replies'] / $_DCACHE['settings']['postperpage'] * 1.5, 15));

这个经典的公式从何而来?由笔者有幸参加的一次DZ的培训得知,这个公式是多年来长期的积累,不断的尝试,才总结所得。至于更多的细节,大概只有DZ的总设计师才能得知。不过我们也可以从代码里得到一些提示,帖子的属性是可以作为是否缓存的权值的,而这个权值,直接决定了缓存与否。

这样的选取在DZ里到处可见,在存在分页的地方,只需要记住,前两页或者前一页,以及最后两页或最后一页,永远比中间的更值得缓存。如果读者的系统需要一个缓存方案,建议全局统计一下所有的用户关注的点,学习DZ,将这些关键的点数值化,就一定也能得出一个合适的公式。

一个简约的缓存,每个细节的方案,筑成了DZ整体的坚实。

提示:平时在设计系统的时候,也许并不能考虑到这么细,如果不是受到磁盘空间的限制,您并不需要担心按照什么方案来缓存,用一刀切的方案也不错,也就是把大部分看上去很常用的数据都缓存了,但你需要更多考虑去对比是否需要更新缓存了,比如用最后回复的时间去对比,很多开源系统就都是这样干的。

Scp和rsync的限制流量(速度)方法

有些机房会限制机器的流量,为了不触及底线,在使用scp和rsync的时候都要注意。

为了避免你的scp或者rsync因为无良&懒惰的OPS设置防火的偷懒而造成的断流现象,我们必须对自己的数据传输进行一定的限流措施,慢一点总比被掐了的好。因此(限制为 1M Bytes/s):

  scp -l 10000 某个大文件   你的账号@远程的机器
或者rsync是(限制为 60k Bytes/s):
  rsync -auvz --progress --delete --bwlimit=60 远程的文件  本地的文件
    rsync -auvz --progress --delete --bwlimit=60 本地的文件  远程的文件

内部培训--memcached协议详解[原创][总结]

[ 文章作者:陈臻 本文版本:v1.0 最后修改:2009.5.12 转载请注明原文链接:http://www.54chen.com/c/584 ]

本次讲座讲师是校内网高手张洁同学,主题是“memcached协议详解及java client分析比较”,java client分析比较线条化,只有在现场才能明白,此处只回顾memcached协议详解,为易于理解,标题段落有调整。

一.连接

安装好memcached,直接通过telnet localhost 11211连接。11211是memcache默认的端口。

二.协议

2.1store (存储)

(可用命令)set/add/replace/prepend/append

<command name> <key> <flags> <exptime> <bytes> [noreply]\r\n

exptime 只能精确到秒 例如:

set name 0 0 5<回车>

zhangjie<回车>

STORED 区别:set可能覆盖,add不能覆盖,prepend是续在前面,append是续在后面。

另:[noreply] 是新版中增加的标志,可以让服务器端不用返回。

2.2 cas(compare and set)

最新版的命令。目的保证执行的原子性。

例如:

cas some 0 0 10 2

意思是:检查some的值的版本是不是2,是2才把10存进去,

2.3 get/gets

get <key>*

get key1\r\n

get key1 key2 key3\r\n gets与get相比,返回结果会多一个版本号:

gets some

VALUE some 0 10 2

2008-03-20

END 2.4 delete(没得说的)

2.5 incr/decr(自增和自减)

2.6 stats(运行状态)

STAT curr_items 1

STAT total_items 7

STAT bytes 58

STAT curr_connections 5

STAT total_connections 6

STAT connection_structures 6

STAT cmd_get 12

STAT cmd_set 11

STAT get_hits 8

STAT get_misses 4

三.两个java client

spymemcached

  http://code..com/p/spymemcached

Java memcached client

  http://www.whalin.com/memcached

关于环状的一致性hash很有意思,有时间研究研究。

[54陈新闻]hhhjob新版(2.0)正式发布了!

hhhjob简介:http://www.hhhjob.com

hhhjob是两年前在学校里开始筹划的一个公益组织,正式上线应该是在08年初的时候,上线后受到了来自各大高校同学的支持,并与现在的大学英语四六级查分站99宿舍建立了良好的合作伙伴关系,08年末受主机商影响,hhhjob经历了很长一段离线时间,以下地址是长期的离线时期所挂靠的页面,欢迎围观:

http://www.54chen.com/hhhjob

hhhjob 2.0简介:

新版的hhhjob同传承了原来的光荣传统,同样非常努力、非常勤奋地收集来自各大名企的师姐师兄,同时号召大家共享出来名企的求职经验和要求,希望能为寻找工作的朋友提供真正有效的信息和真正有用的职位。

组织成员:
总体方案:tangyu 、cc0cc 、偏偏
策划:tangyu
程序:cc0cc
日常事务: zeno、莞尔、enya、ruyi、Missfly、asura、莫非非、alexlee、dingxx、king、dennis、javawz、guyu、wahaha

在此一并感谢dbanotes.net的Fenng同学和weibo上一帮有意思的朋友,你们的意见都将是hhhjob组织未来发展的强心剂。

这次新版本还有一个特色是黑名单企业的提交,是来自guyu同学的奇思妙想。

[54陈科学院]802.1x源代码下载

免责声明:

本程序仅供学习编程使用,非商业用途,所有分析过程均遵循《计算机软件保护条例》。

功能:

mynet是我在大学时期在xdkui老兄的vc源码参考下,完成的一套gnome程序,它解决了linux下802.1x拔号上网问题,同时友好的界面能使你轻松使用。

截图:

代码分析:

[中秋零献] 神州数码802.1x局域网UDP拔号软件MyNet-Gnome源代码大分析(Part1)

[中秋零献] 神州数码802.1x局域网UDP拔号软件MyNet-Gnome源代码大分析(Part2)

[中秋零献] 神州数码802.1x局域网UDP拔号软件MyNet-Gnome源代码大分析(Part3)关键逻辑

[中秋零献续集] 神州数码802.1x局域网UDP拔号软件MyNet-Gnome源代码大分析(Part4)getaccess线程内的故事

索取代码,请猛击此处进入此页面留下邮箱。

[原创][实测]MySQL时间字段究竟使用INT还是DateTime?

[ 文章作者:陈臻 本文版本:v1.0 最后修改:2009.4.27 转载请注明原文链接:http://www.54chen.com/c/560 ]

环境:
Windows XP PHP Version 5.2.9
MySQL Server 5.1

第一步、创建一个表date_test(非定长、int时间)

CREATE TABLE `test`.`date_test` (
`id` INT NOT NULL AUTO_INCREMENT ,
`start_time` INT NOT NULL ,
`some_content` VARCHAR( 255 ) NOT NULL ,
PRIMARY KEY ( `id` )
) ENGINE = InnoDB;

第二步、创建第二个表date_test2(定长、int时间)

CREATE TABLE `test`.`date_test2` (
`id` INT NOT NULL AUTO_INCREMENT ,
`start_time` INT NOT NULL ,
`some_content` CHAR( 255 ) NOT NULL ,
PRIMARY KEY ( `id` )
) ENGINE = InnoDB;

第三步、创建第三个date_test3(varchar、datetime时间)

CREATE TABLE `test`.`date_test3` (
`id` INT NOT NULL AUTO_INCREMENT ,
`start_time` DATETIME NOT NULL ,
`some_content` VARCHAR( 255 ) NOT NULL ,
PRIMARY KEY ( `id` )
) ENGINE = InnoDB;

第四步、创建第四个表date_test3(char、datetime时间)

CREATE TABLE `test`.`date_test4` (
`id` INT NOT NULL AUTO_INCREMENT ,
`start_time` DATETIME NOT NULL ,
`some_content` CHAR( 255 ) NOT NULL ,
PRIMARY KEY ( `id` )
) ENGINE = InnoDB;

ok,现在我们开始做测试,环境是php,先向各个表插入一百万条数据。插入的时候分200次,每次进库5000条。

表一执行记录:页面运行时间: 26.5997889042 秒,插入的时候发现一个有趣的现象:SELECT count( id ) FROM `date_test` WHERE 1 的结果是100w,而直接select * from `date_test`却是1,000,374条结果。(后来看到这是一个可能接近的值,请参看MySQL FAQ 3.11)。
表二执行记录:页面运行时间: 62.3908278942 秒,这次记录是1,000,066条。
表三执行记录:页面运行时间: 30.2576560974 秒,这次的是1,000,224条。
表四执行记录:页面运行时间: 67.5393900871 秒,这次的是:1,000,073条。

现在把四个表的start_time字段一一加上索引。

测试四个表的更新,分别update 100条记录,并记录时间:
表一:页面运行时间: 2.62180089951 秒(非定长,int时间)
表二:页面运行时间: 2.5475358963 秒(定长,int时间)
表三:页面运行时间: 2.45077300072 秒(varchar,datetime时间)
表四:页面运行时间: 2.82798409462 秒(char,datetime时间)

测试四个表的读取,分别select 100条随机记录,以主键id为条件查询,并记录时间:
表一:页面运行时间: 0.382651090622 秒(非定长,int时间)
表二:页面运行时间: 0.542181015015 秒(定长,int时间)
表三:页面运行时间: 0.334048032761 秒(varchar,datetime时间)
表四:页面运行时间: 0.506206989288 秒(char,datetime时间)

测试四个表的读取,分别select 10条随机记录,以star_time为条件查询,并记录时间:
表一:页面运行时间: 30.1972880363 秒(非定长,int时间)
表二:页面运行时间: 65.1926910877 秒(定长,int时间)
表三:页面运行时间: 39.7210869789 秒(varchar,datetime时间)
表四:页面运行时间: 70.4632740021 秒(char,datetime时间)

因为量比较小,所以我们默认即使是微小的变化,也是有意义的。

结论:

大数据量下,如果存在大量的select * from table where 时间>XX这样的查询,在MySQL5.1时使用int换datetime是有意义的。

[54chen出品][打酱油]在线一对一和陌生人聊天的网站

      打酱油(http://www.dajoyo.com)是一种生活方式,既不是简单的路过,也不是单纯的看热闹。

      和一个随机的陌生人聊天。谁也不知道你是谁,谁也不知道你会遇见谁。可以放心倾诉、交友甚至发泄,因为大家都在打酱油。
       聊天对象虽然是随机的,陌生的,不过如果你愿意,谁也不能阻止你透露自己的个人信息。朋友,或许就从打酱油开始。缘分,是天注定吗?那么现在就开始:

 

如果有什么问题,欢迎在这里留言,很乐意听到大家的意见。

【友情提示】

打酱油使用了最新的p2p技术,需要穿透您的网络,所以当您的安全性设置较高时会出现连接错误,出现这样的问题时,请尝试将防火安全级别调低,另外请有链接出错或者进入无反应的朋友提供您的网络情况,帮助打酱油成长。

[原创][整理]校内网CTO晶讲述网站架构变迁-54chen回忆版

[文章作者:陈臻 本文版本:v1.1 最后修改:2009.4.13 转载请注明原文链接:http://www.54chen.com/c/539 ]

这是一次公司内部的交流会,主题是校内的发展史和构架讲解,主讲人是校内网CTO晶,其中关于架构变迁的一段个人觉得是很具有性的过程,特在会上作了大概的笔记,现在是凌晨一点不到,正好清醒头脑进行回忆总结。

每个网站的发展都会按照一个大致相同的路线去完成,当然这里说的是每个相对成功的网站。

第一阶段:

这一阶段没有太大的访问量,甚至只有一台服务器就搞定了所有的访问。DB和前端的代码全都在一起,压力不高。忆者注:我觉得在alexa没进五万的时候,只要不是特殊的应用,基本都在此列吧。

第二阶段:

网站初具规模,DB压力大增,单独的一台DB已经满足不了现在的访问量,开始考虑读写分离的Master-slave库,使用三个及以上的服务器。忆者注:这时网站的alexa基本上会在1-3万的位置,每天的ip在5-10w的样子,当然,DB我们都认为是MySql。

第三阶段:

访问量继续增加,增加到了DB的压力在Master的机器上非常的明显了,Master开始出现吃不消的情况,出现写耗尽。主从也已经不能满足要求,需要进一步解决负载问题,此时要引入Mysql Proxy程序,进行中间层代理,实现负载均衡,易于扩展。忆者注:这时网站已经不可限量了,先恭喜下你的网站能用到这段。

第四阶段:

网站继续发展,进而出现了数据量的成倍增长,原来的N台DB都出现了一个问题,数据量巨大,无法完成正常速度的读写。此时,需要对网站按功能进行垂直划分,比如用户注册登录是一部分、UGC又是另一部分。与此同时,对数据本身进行水平划分,也就是Hash散表或者是散库。

第五阶段:

真的没了。再往下玩就灭了。

其实再进一步第五第六阶段,就是无法预想的未来了,也许有什么突飞猛进的科学技术发明也说不好。

今天和yahoo的agentZhang(openResty作者)聊起,他说到第五个阶段其实应该是BigTable,的确很强大,来自的作品。不过美中不足的是,它并不像我相像中的那样能够顺利过渡到第五阶段。以下论述来自infoQ:
Todd从定义BigTable的适用范围开始论述。由于BigTable引入的各种代价,只有在以下情况下使用BigTable才能带来益处:a)需要伸缩到巨量的用户数,b)更新与读取作相比比例很小。Todd还着重强调为了“优化读取速度和可伸缩性”,所采取的理论路线与关系数据库中的做法存在根本的分歧,很可能初看起来是违背直觉甚至相当冒险的。

Gae Java支持试用手记

一直都对gae冷眼旁观,今天得知支持java,甚是兴奋,是否暗示python也向java低头了,记一篇手记,送给万千不怕的同志。

首先用你的GAE账号登录http://appengine..com/start/newtos,当然,如果你没有GAE账号的话,得申请一下,过程要用手机接验证码,传说是不要钱的。

点上,发送submit。

登录进GAE,有一个明显的条提醒:Interested in trying our new Java language support? Learn more

点learn more进去后Sign up to try App Engine for Java。downloading the SDK.这是SDK下载。

点sign me up。

Thanks for signing up. Once your account is activated, you will receive an email with more information.

然后等待激活java支持,激活了会有邮件通知。

====

提供了一个eclipse的插件,十分好用,遗憾之处在于,update install相当的慢,公司的网络也一度最快为1k/s...

下面是此次 Campfire上关于GAE的一些有用的链接:

申请试用GAE for JAVA的链接页面

Code Blog上介绍GAE的最新功能

Campfire首页介绍GAE JAVA

GAE JAVA的入门指南