Sunday, March 13, 2011 1:47:13 PM
memcache
上次说每周挑个觉得有点料的分享从自己理解的角度做个分析,第一个就拿2010Qcon北京上的这个篇Memcache@Facebook开始。
Facebook对Memcache存在非常强的依赖,看下他们的数据:

Facebook挑战从2006年放开用户限制的时候开始,原来不同学校的用户是相互隔离的。因为每一位Facebook的用户的好友可能遍布全球,所以Facebook要解决的问题就是如何快速的跨服务器获取数据,不管那台服务器在什么地方。Facebook依靠Memcache来加速数据访问。
由于PHP在运行时是单线程并且是同步的,为了提高数据并行获取的速度,Facebook将对Memcache的操作变成并行的(使用了AIO)
根据缓存对象的大小和访问策略将其存放在不同的Memcache服务器上,用以获得更好的缓存访问速度和内存使用率。(这个主要是和Memcache内存分配机制有关系)
Facebook在每台Memcache服务器上是跑了4个Memcache实例的,所以每个机器的上面的连接消耗比较大,使用UDP减少连接。
改用了新的序列化方法(fb-serialization),并做压缩。
多数据中心同步
同一地区:
数据库层是单一的集群,但是Memcache是两个,Memcache前段使用一个特殊的代理用来跨Memcache集群做访问。
不同地区:
为了避免其它地区用户的延时,部署了slave DB,增加了程序对数据库上的更新和删除触发Memcache上的delete操作。同样使用了proxy。
Replicated Keys:
对于某些热门的缓存对象的访问会超过单一服务器的处理能力(因为对对缓存的key做过独特的路由),对key做别名解决这个问题。于是get key:XXX变成了 get key:XXX#N
为了避免热门对象对数据库造成冲击(因为缓存没有命中的时候会去去数据库),使用key:xxx#mutex的方法,就是去数据库查之前先增加一个mutex缓存对象,成功了再去读数据库,然后将对象缓存到Memcache然后把删掉mutex缓存,如果add mutex失败则重试。不过mutex解决不了需要频繁更新的对象的问题。
Memcache使用原则
- 优先从Memcache获取对象,如果没有命中则查询数据库并将这个对象放到Memcache中。
- 在数据库中更新数据的时候删除Memcache中对应的对象。
- Memcache中不会存放衍生对象,所有缓存的对象都数据库中持久化的数据直接映射。
- 对于热门的缓存key,使用别名,对应的在数据被更新的时候则要删除所有的别名缓存。
- Memcache服务器是检测内存的最佳位置,记录删除,命中失败等
Tuesday, January 18, 2011 10:58:30 AM
sae, php
昨天稍微提了以下SAE中的TaskQueue,其API和GAE中的TaskQueue基本一样,呃,名字也一样。TaskQueue其实是普通消息队列的一个变种,增加的是有一个默认的消费者,根据消息的描述对指定url发起请求。
$queue->addTask("http://freedemo.sinaapp.com/page2.php", "aaaa", true);
SAE中的TaskQueue分为两种,第一是顺序队列,另外一种是并发队列。其实所谓并发队列就是可能存在N个消费者,这种情况下自然不会保证顺序了。从现在的限制来看允许堆积的量还是比较少的。当然小应用应该没什么问题。并发队列最大阻塞数1024个。Task中的url是要执行的任务的url,可以用post传递参数。
要说的一点是这个addTask函数的参数类型值得商榷。
bool addTask (string|array $tasks, [string $postdata = NULL], [bool $prior = false], [array $options = array()])
从定义我们可以看到postdata用的类型是string,这就意味着如果传递多个参数的时候要自己来拼这个string。自己包装下也没什么问题,但是这里如果是个array会更合理一点。
自己拼一下吧。
function array_join($array, $ch = '&') {
$join = array();
if (is_array($array)) {
foreach ($array as $key => $value) {
$join[] = "${key}=${value}";
}
}
return $s = implode("&", $join);
}
php函数能够指定默认参数真好!
用TaskQueue的时候测试有点麻烦,不过还是有一些方案,最直接的,用curl发起http post请求。
curl -d 'param1=value1¶m2=value2' http://app.sinaapp.com/request
Queue和Cache,至爱啊。
Monday, January 17, 2011 3:07:50 PM
sae, php
今天干了两件事情,第一件使用fetch_url抓取快递公司数据的时候增加了memcache的操作。fetch_url比较昂贵,另外接口api的响应状况不是很好。代码大致是这样子。只要请求成功了,就把结果先缓存起来,设置一个有效时间,这样重复点击或者刷新就可以直接走Cache返回了。
$mmc = memcache_init();
$key = hash("sha512", $url);
$content = $mmc->get($key);
if (!$content) {
$f = new SaeFetchurl();
$content = $f->fetch($url);
if ($content === false) {
var_dump($f->errno(), $f->errmsg());
} else {
$mmc->set($mmc, $key, $content, 60);
}
}
第二件,定时任务走task queue。SAE的task queue api和GAE的类似,不过现在有点不给力的是并发Queue长度太小,第二传递的参数的类型定义的是一个string,而不是一个array。
Monday, January 17, 2011 3:06:03 PM
sae, php
express.sinaapp.com是在我在SAE做的一款应用,主要是用来跟踪快递,结合现在的sina微博账号,进行反馈通知。呃,其实PHP对于我来说完全是从零开始,个人基本上是Java后端为主。呃,幸好PHP上手还算容易。
使用了SpeedPHP框架,差强人意。显然一开始就陷入框架里并不是一个什么好主意,不过PHP里面的框架要比Java里面的小的多。前端Javascript库使用了JQuery,恩,文档很多。
快递数据使用快递100提供的api,呃,不得不说快递公司的这些系统真是太烂了,接口稳定性很差,凑合着用。
SAE现在的在线编辑不支持版本管理,本地呢又没有开发工具,这个真是有点猥琐。提了建议给他们,据说是以后会支持git,不知道有没有打算支持本地开发环境。系统如果规模大一点,直接线上测试实在是有点不靠谱。
Wednesday, January 5, 2011 7:49:20 AM
aio, oracle
最近做的一次性能测试需要测的业务会有在执行过程中会有比较多的数据写入,但是测试环境的数据库只有一块硬盘,io能力不够。TPS最多只能支持到100左右,数据库的IO就扛不住了,比较高的IOwait让响应时间变得不可接受。尝试之后发现两三个并发就能把数据库的IO压满了。种种原因,想去搞台更好的测试服务器是不靠谱的了,只能看看数据库这边能不能优化一下。
无意中看到了FILESYSTEMIO_OPTIONS这个参数,发现性能db用的是none,于是尝试改成aio试试。
alter system set filesystemio_options = asynch scope=spfile;
shutdown immediate;
startup;
重新压测,并用iostat监测数据库的io情况
iostat 1
iowait基本是在零点几波动。
从awr里也能看到原来几个比较top的io事件的时间也变得能够接受。比如这个log file sync,当io争用不明显时它的平均等待时间也降低了。原来都能达到20多ms。
Avg
wait % DB
Event Waits Time(s) (ms) time Wait Class
------------------------------ ------------ ----------- ------ ------ ----------
DB CPU 1,090 54.5
log file sync 171,262 253 1 12.7 Commit
这里有关于Oracle 11里面IOPS测试的内容
FILESYSTEMIO_OPTIONS说明
Sunday, December 12, 2010 2:53:41 PM
dream
如果不是在豆瓣上看了影评或许我不会去看优酷上这部短片,然而当我看完第一遍的时候我又接着看了第二遍。
不知道有多少人看到这里的时候已经泪流满面,生活就是这个样子,怀揣着梦想跨出校门,不知道有多少在生活的挤压下完全变成了另一个人,如同片尾那首歌唱的那样,
青春如同奔流的江河,一去不回来不及道别,只剩下麻木的我没有了当年的热血
耳边依稀想起当年石头问我的话,若干年后,你还能有这样的梦想吗?
当初的愿望实现了吗
事到如今只好祭奠吗
任岁月风干理想再也找不回真的我...
Sunday, December 5, 2010 1:18:14 PM
Java, play
Play在java web框架里算是有所创新,我知道这个时间也不断了,只是一直没仔细看过。Java其实限于语言本身的特性,想弄成如rails般高生产率确实不容易。
play+scala的话不知道能不能玩的爽一点?
Tuesday, September 7, 2010 2:59:56 PM
作为一名架构师,追求完美是一种必备的品质。然而总是有各种原因,有时候是因为业务原因,有时候是因为其它已经存在的系统的原因,你都要选择折中,对于应用架构,这种情况更为多见。尽管,在这种事情上“妥协”就好像午饭时不小心迟到了苍蝇一样,但是却无法避免。
当然,trade off也要有原则,有选择性,在有可能的情况下尽量的采用过渡方案而不是临时方案。
尽管经常会吞到苍蝇,但是也要一直保持警惕,不要让系统在不经意的一些变化中,慢慢的变成了一坨意大利面。