手机浏览 RSS 2.0 订阅 膘叔的简单人生 , 腾讯云RDS购买 | 超便宜的Vultr , 注册 | 登陆
浏览模式: 标准 | 列表2010年04月25日的文章

KESO:Google一次的能耗

好象这次KESO的《Google一次的能耗》引起了很多人的关注,特别是在QQ微勃上面,有人的转贴就是:不知道http://url.cn/0k4vVU消耗多少,硬件软件有重新设计过吗?|| 腾讯科技  keso炮轰人民网

KESO的原文不长,我这里稍转一下,三言二拍:Google一次的能耗

人民网上有一篇文章,说每次Google搜索的能耗,相当于100瓦灯泡工作一小时。其中充斥着大量的错误,既有原文的错误(原文在此),也有翻译的错误。

比如,翻译中说,“谷歌数据中心拥有近100万台服务器,每台服务器每小时消耗大约1000瓦的电量”。瓦特是功率,不是电量,电量我们一般用度 (千瓦时)来表示。再比如,“这个搜索引擎每小时产生近1000万个搜索结果”,实际上,早在2001年,Google每天的搜索请求量就超过了1亿次, 今天这 一数字早已超过10亿次(Twitter的日查询次数,包括各种客户端的请求,都高达6亿次)。

上面是明显的错误,其他错误还包括,按每台服务器功耗1000瓦的标准计算Google服务器的能耗,也是相当不靠谱的。普通PC服务器的功耗,一般在400-500瓦。Google的服务器、机房、电源、甚至冷却系统,都是自己设计生产的,按照Google公开的数据,Google服务器的电能转换效率是业界最高的。

而且,把全部服务器的能耗,平均到每次查询上,也非常不靠谱。Google每天要存储20PB的UGC数据(相当于20,000TB,或者 20,000,000GB),假设每块硬盘的容量是1TB(1000GB),那么用户每天产生的内容要写满2万块硬盘。在Google庞大的数据中心中, 有大量服务器实际上是存储服务器。

按照Google自己的计算,一次搜索查询的能耗,大约只相当于0.0003度(千瓦时),或者1千焦(1千瓦时=3600千焦),如果是100瓦的灯泡,这些能量只能点亮11秒钟。

写到这里,我觉得这种计算其实挺无聊的。Google当然会想尽办法节省能源,毕竟它的百万规模的服务器数量,在节能上哪怕非常微不足道的一点小进步,都意味着巨大的资金节省。能源账到底该怎么算,恐怕不是个简单的算术题。

节能是必要的,也是可能的,但搜索技术带来的巨大的社会进步和其他损耗的减少,是在上面的计算中完全看不到的。能源账到底该怎么算,恐怕不是个简单的算术题。

--EOF--

转载的文章嘛。不多点评,不过我是知道国内大多数的机房,其实有很多都在空转着。大量的电力、网络都被IDC消耗掉了。不过想想也很正常,承租机柜后如果没有业务,机柜怎么办?关掉?而且,即使你用的电源低于标准的400W,也没有减少他们应收的费用。更加让人郁闷的是,国内很多大型网站的老总都是这么认为的:能用钱解决的问题就不是问题(比如,服务器、带宽等)。因此,说google的时候,考虑一下自己才是重要的。

国内,好象就听说阿里有自己的机房,不知道他们在缴纳每年的电费时,是否也在考虑着要节约电力?要思考如何改进架构?至于我们这些P民,用着租来的、托管的机器,或许,想的是真的要少一点吧?

Tags: keso, google, 微勃, 微博, qq微博

重要的不是语言,是思想

标题这种话已经在被很多人所理解,现在大多数开发人员已经不再把语言当成障碍,而是把思想当成障碍,语言的跨度其实真的很容易解决,但思想不进步,你有着再好的语言又怎么样?即使你用的是所谓的自然语言(即平时生活中的语句),但只要你没有思想,没有逻辑,你又能写出什么样的程序?

以下内容来自老王参加的某大会的记录、摘要。我是看中其中的一小部分,觉得有感触。。原文在这里,点击进入

部分我认为不错的精华,或者说是我关注的。。。

1、课程:失败来临的征兆(讲师:Michael Nvgard)这一切正是Michael Nvgard先生演讲的主旨:意外的问题总是在不经意间发生,要注意把它们的影响限制在局部,避免拖累整个应用。比如说在SOA中集成若干个服务时,应该 设置好各个服务的Timeout,避免其中一个服务崩溃连带整个系统等待。

2、课程:Twitter的可伸缩性数据架构(讲师:Nick Kallen)

Nick Kallen介绍了Twitter在处理海量数据时的经验,其实总结出来就三条:分区,索引,复制。

着重介绍了Tweets,Timelines,Social Graphs,Search Indices四个基本功能的实现:

Tweets比较简单,就是分区,虽然可以使用id或者user_id来分区,不过目前Twitter使用的是按time分区。

Timelines相对复杂了一些,最开始采用的方法是纯SQL的,大致如下:

SQL代码
  1. SELECT * FROM tweets  
  2. WHERE user_id IN (SELECT source_id FROM followers WHERE destination_id = ?)  
  3. ORDER BY created_at DESC  
  4. LIMIT 20  
这当然不是一个高效的解决方案,后来采用了被称作离线计算(Offline Computation)的解决方案,其思路大致就是每当发送一条推的时候,采用队列存储避免峰值瓶颈,同时向所有Followers分发此消息,然后每 个分发 终端在缓存中完成合并计算。乍一听起来这似乎也不是什么好的解决方案,一旦某人有非常多的Followers,即便分区,这个分发操作也会非常耗时,但按 Nick Kallen的介绍,Twitter确实是这么做的,细节操作有待研究。

剩下的问题不多说了,Nick Kallen给了PPT地址:http://www.slideshare.net/nkallen/q-con-3770885

3、课程:构建可扩展的微波系统(讲师:杨卫华)

杨卫华作为新浪微博的架构师,这次的PPT做得很酷,虽然在内容上和Twitter有些重复,但还是很不错。

提到了Memcached的evictions问题,给出了三个守则:

1:规划好cache的容量
2:将永久数据和临时性数据分开
3:不使用随机字符串做Key

至于原因,可以参考杨卫华的博客上的介绍:Memcached数据被踢(evictions>0)现象分析

4、课程:敏捷在中国(讲师:Tom Mellor) 编程工期的催促往往让程序员只考虑眼前的既得利益,却忽视了后期的风险。

5、课程:如何在团队中有效实施TDD(讲师:麦天志)在阐述为什么即便工期紧张也应该使用TDD的时候,他给了一个比喻:医生做手术的时间很紧张,但即便 这样,手术前清洗双手的工作程序也是必不可少的。在讲解重构时,他强调了TDD是重构的基础,只有这样才能保证重构没有改变现有的行为,否则就不是重构,而是重写。

Tags: 语言, 思想, 参考

例行维护后引起的故障和桔子的缓存故障

最近javaeye发生一起小故障,是robbin自己说的:

XML/HTML代码
  1. @robbinfan: 昨晚JE所在机房切换电源关机导致网站无法访问。早上恢复后因为数据库和缓存服务器都被清空,巨大流量(QPS将近400,并发连接到1000)直接冲击导致web服务被阻塞,现在正在逐步恢复中。

在mikespook.com看到对待这个问题的分析时,突然想起桔子也遇到过类似的问题,所以把他们两个人的事情贴出来。

先上mikespook的:

XML/HTML代码
  1. 显然,这是一次运维事故。事故的原因是分流作用的数据库和缓存出现“故障”,导致数据层响应延迟,web 服务器阻塞。这里我没有用“清空”而是用了“故障”来描述分流数据库和缓存,是因为实质上 javaeye 的这次事故虽然是正常维护(电源切换)后发生的,但是其表象跟分流数据库和缓存宕机是一样的。  
  2.   
  3. 这个故事给我的两个启示:  
  4.   
  5. 在架构设计上,对于分流数据库或者缓存或许应有一定的持久化能力。比如,在维护时,按照从“外”到“内”的顺序逐步关闭服务。在这个例子里,“外” 就是 web服务,“内”就是数据层。在关闭了“外”服务后,手工或自动将缓存持久化。维护完成,开启顺序从“内”到“外”,并在回复完底层存储后,将持久化数据恢复到缓存。  
  6.   
  7. 在运维规范上,在维护后应让系统进入一个的磨合期,在合理的时间内通过分流(比如跳转到一个“系统忙”的页面)或者防火墙封锁的方式。让系统保持在比正常负载低一些的水平。持续一段时间(或者维护后累计访问量达到某个值)后再让系统开足马力去运行。  
  8.   
  9. 这样,应该可以避免空缓存大并发导致的宕机事故。  
  10.   
  11. 再次感谢 robbin 和 javaeye 为我们带来的启示。  

再上桔子的,汗,突然发现桔子的博客上居然没有写,看来是上次在群里看到了,大意如下:

XML/HTML代码
  1. 某次更新系统,然后需要重启,结果重启后CPU长时间处于100%(?还是死机了?),后来检查发现,原来故障是出在缓存上。  
  2. 因为是采用文件缓存,而又设定了过期时间,重启后,所有的缓存都过期了。然后网站访问量又大,突然而来的访问导致缓存重新生成,差点让机器出故障。  
  3. 所以现在开始要调整缓存架构。  
其实上面两个问题都差不多。都是在访问大的时候,缓存频繁生成造成的故障,这确实不容忽略,但如何解决真的是一个问题。很多时候在访问量不大时,我们都考虑使用文件来作为缓存存储。但真正访问量高了后,文件缓存不可避免的就带来IO的消耗,如何批量生成缓存?还是按次生成缓存?还是定有一定的策略?难道还要采用队列?那就夸张了。

所以,一个好的系统架构也是很需要的,不能因为一次宕机就永远起不来。我个人是偏向于队列生成缓存,这样就不用担心一次写入过多文件引起IO的崩溃。但队列是因为有延迟的,如果控制同样的内容不重复生成文件缓存,则需要另外考虑

Tags: 故障, 缓存, 重启, 维护

MySQL和SQL字段截短漏洞

这篇文章很有意思,以前注意过,但没仔细考虑过用来注入,或许就象王猛说的:

    了解很长一段时间的web安全了,个人觉得世上最聪明的程序员其实是黑客,一次想N步,逻辑超强,技术全面,从操作系统漏洞、到语言本身漏洞、数据库本身漏洞、再到开发者代码,无孔不入。

文章来自寂寞hacker,http://hi.baidu.com/isbx/blog/item/08ef48547ef1ad58574e00bf.html:
当前的Web开发者中肯定有不少人没有注意到作者所提到的这两个问题的。

第一个问题是这样的,MySQL默认有一个配置参数 max_packet_size,这个参数是用于限制MySQL客户端和MySQL服务器端数据通信的数据包大小,MySQL的默认配置是1MB。如果客 户端发送的数据超过了1MB,则MySQL服务器端会忽略掉这个请求数据。作者接下来举了两个利用这个缺陷的例子,第一个是利用超长数据来使MySQL的 日志记录程序失效,第二个是在PHP+MySQL的环境下,PHP的Session清理程序会由于一次发送的清理session数据的请求数据包超过 max_packet_size的限制,而导致清理session失败。

而实际上,由于很多PHP+MySQL的程序都会运行用户上传附件之类,而一般的PHP+MySQL的上传附件限制都是大于1MB的,所以PHP的 程序开发人员一般是会去修改max_packet_size的值为大于1MB。这就给我们的漏洞利用带来了一定的麻烦,毕竟在当前的网络状况下,构造 1MB多的数据去上传还是可以忍受的。但是太大的数据量就比较考验我们的耐心了,呵呵。

第二个问题就比较严重了,MySQL对于超过字段长度的数据插入操作会进行默认的字符串截短。例如一个字段定义的长度为10,如果插入的字符串长度 超过10,MySQL会将长度超过10的部分字符串自动舍去后插入到数据表中。默认配置条件下,MySQL会产生一个警告信息,但是这个警告信息不会被 Web应用程序捕获到。所以,从表面上来看,超长数据也是可以“成功”插入数据表的。作者在下面举的这个例子就很有代表性了,首先是一个场景假设:

  • The application is a forum where new users can register
  • The administrator’s name is known e.g. ‘admin’
  • MySQL is used in the default mode
  • There is no application restriction on the length of new user names
  • The database column username is limited to 16 characters

用户如果尝试注册一个用户名为admin的用户,会由于Web应用程序中的isAlreadyRegistered函数的校验而注册失败。

SQL代码
  1. SELECT * FROM user WHERE username='admin'  

但如果用户使用用户名’admin           x’来注册(注意admin和x之间有11个空格),则注册流程会是这样的:

isAlreadyRegistered函数会使用上面的SQL语句来检查user表中是否存在相同用户名的用户,查询结果肯定是不存在的。那么用户注册成功!

实际上,真正插入到user表中的用户名是’admin’!也就是说,MySQL不仅会截短超过长度限制部分的字符串,也会对字符串头尾的空白字符进行截短!所以,在user表中,现在存在了两个admin用户!

接下来,用户登陆,他使用的是用户名admin,密码是他刚才设置的’admin           x’的密码。假设Web应用程序的登陆认证和授权函数是这样的一段代码:

PHP代码
  1. $userdata = null;  
  2. if (isPasswordCorrect($username$password)) {  
  3.    $userdata = getUserDataByLogin($username);  
  4.    ...  
  5. }  

其中isPasswordCorrect函数使用的SQL语句为:

SQL代码
  1. SELECT username FROM users WHERE username = ? AND passhash = ?  

getUserDataByLogin函数使用的SQL语句为:

SQL代码
  1. SELECT * FROM users WHERE username = ?  

可以看得出,上面的语句使用了预编译的SQL语句,是无法实施SQL注入的。但是由于MySQL的默认字段截短策 略,isPasswordCorrect函数会成功执行并返回用户名admin,接下来的getUserDataByLogin也会正确执行,返回的结果 虽然是一个数组,但是Web应用程序一般是取返回数组中的第一个结果,也就是真正的管理员用户admin的所有数据!

怎么样,不用SQL注入,一样拿到管理员权限!

后记:经过测试,上面的漏洞利用过程在MySQL 4中是确实存在并且可以利用的。但是在MySQL 5中,本机测试失败。失败的关键就在于MySQL 5对于超过字段长度限制的字符串插入会报错,并停止字符串插入操作。

附:MySQL 4的测试过程

SQL代码
  1. mysql> select * from tb_sqltest where name='jason';  
  2. +----+-------+--------+------+------+------+------+  
  3. | id | name  | remark | time | col1 | col2 | col3 |  
  4. +----+-------+--------+------+------+------+------+  
  5. |  1 | jason | NULL    | NULL | NULL | NULL | NULL |  
  6. +----+-------+--------+------+------+------+------+  
  7. 1 row in set  
  8.   
  9. mysql> select * from tb_sqltest where name='jason        x';  
  10. Empty set  
  11.   
  12. mysql> insert into tb_sqltest (id,namevalues (2,'jason        x');  
  13. Query OK, 1 row affected  
  14.   
  15. mysql> select * from tb_sqltest where name='jason';  
  16. +----+-------+--------+------+------+------+------+  
  17. | id | name  | remark | time | col1 | col2 | col3 |  
  18. +----+-------+--------+------+------+------+------+  
  19. |  1 | jason | NULL    | NULL | NULL | NULL | NULL |  
  20. |  2 | jason | NULL    | NULL | NULL | NULL | NULL |  
  21. +----+-------+--------+------+------+------+------+  
  22. rows in set  

 

 

 

 

 

Tags: mysql