16:38 Twitter的中文用户数量 » WebLeOn's Blog
最近@sioksiok和@sunzhifeng都问到关于Twitter上中文用户的数量,这个问题的很难。按照目前我所知道的方法,几乎没有办法去得到一个相对准确的数字。正好在半年前,我用TwitDir做过一个非常不靠谱的统计。现在就再使用同样的方法来大致勾画一下中文Twitter用户的数量级。

以上这些数据表示的是对表格中的关键词,在TwitDir中的搜索结果数量。虽然不能直接的说明什么问题,但可以看出来一些趋势。Twitter在中国大陆地区的用户增长速度比台湾及香港要快,不过和整个Twitter用户的增长速度来比,还是要慢了一大截。Twitter在中文地区,还是很小众很小众的东西。
13:59 Navicat MySQL Admin Tool - the World's Best MySQL GUI for Windows, Linux & Mac OS X - Download Now! Support Access to MySQL, Excel to MySQL, MySQL editor, MySQL administrator, MySQL frontend, MySQL manager, phpmyadmin, MySQL mangement, MySQL administratio » del.icio.us/chedong
MySQL客户端,支持ssh 通道;
大量小文件的实时同步方案灵感点滴 » Che, Dong's shared items in Google Reader

传统的文件同步方案有rsync(单向) 和 unison(双向)等,它们需要扫描所有文件后进行比对,差量传输。如果文件数量达到了百万甚至千万量级,扫描所有文件将非常耗时。而且正在发生变化的往往是其中很少的一部分,这是非常低效的方式。

之前看了Amazon的Dynamo的设计文档,它们每个节点的数据是通过Hash Tree来实现同步,既有通过日志来同步的软实时特点(msyql, bdb等),也可以保证最终数据的一致性(rsync, unison等)。Hash Tree的大体思路是将所有数据存储成树状结构,每个节点的Hash是其所有子节点的Hash的Hash,叶子节点的Hash是其内容的Hash。这样一旦某个节点发生变化,其Hash的变化会迅速传播到根节点。需要同步的系统只需要不断查询跟节点的hash,一旦有变化,顺着树状结构就能够在logN级别的时间找到发生变化的内容,马上同步。

文件系统天然的是树状结构,尽管不是平衡的数。如果文件的修改时间是可靠的,可以表征文件的变化,那就可以用它作为文件的Hash值。另一方面,文件的修改通常是按顺序执行的,后修改的文件比早修改的文件具有更大的修改时间,这样就可以把一个目录内的最大修改时间作为它的修改时间,以实现Hash Tree。这样,一旦某个文件被修改,修改时间的信息就会迅速传播到根目录。

一般的文件系统都不是这样做的,目录的修改时间表示的是目录结构最后发生变化的时间,不包括子目录,否则会不堪重负。因为我们需要自己实现这个功能,利用Linux 2.6内核的新特性inotify获得某个目录内文件发生变化的信息,并把其修改时间传播到它的上级目录(以及再上级目录)。Python 有 pyinotify,watch.py的代码如下:

#!/usr/bin/python from pyinotify import * import os, os.path flags = IN_CLOSE_WRITE|IN_CREATE|IN_Q_OVERFLOW dirs = {} base = '/log/lighttpd/cache/images/icon/u241' base = 'tmp' class UpdateParentDir(ProcessEvent): def process_IN_CLOSE_WRITE(self, event): print 'modify', event.pathname mtime = os.path.getmtime(event.pathname) p = event.path while p.startswith(base): m = os.path.getmtime(p) if m < mtime: print 'update', p os.utime(p, (mtime,mtime)) elif m > mtime: mtime = m p = os.path.dirname(p) process_IN_MODIFY = process_IN_CLOSE_WRITE def process_IN_Q_OVERFLOW(self, event): print 'over flow' max_queued_events.value *= 2 def process_default(self, event): pass wm = WatchManager() notifier = Notifier(wm, UpdateParentDir()) dirs.update(wm.add_watch(base, flags, rec=True, auto_add=True)) notifier.loop()

在已经有Hash Tree的时候,同步就比较简单了,不停地获取根目录的修改时间并顺着目录结构往下找即可。需要注意的是,在更新完文件后,需要设置修改时间为原文件的修改时间,目录也是,保证Hash Tree的一致性,否则没法同步。mirror.py的代码如下 #!/usr/bin/python import sys,time,re,urllib import os,os.path from os.path import exists, isdir, getmtime src = sys.argv[1] dst = sys.argv[2] def local_mirror(src, dst): if exists(dst) and mtime == getmtime(dst): return if not isdir(src): print 'update:', dst open(dst,'wb').write(open(src).read()) else: if not exists(dst): os.makedirs(dst) for filename in os.listdir(src): local_mirror(os.path.join(src,filename), os.path.join(dst,filename)) os.utime(dst, (mtime,mtime)) def get_info(path): f = urllib.urlopen(path) mtime = f.headers.get('Last-Modified') if mtime: mtime = time.mktime(time.strptime(mtime, '%a, %d %b %Y %H:%M:%S %Z')) content = f.read() f.close() return int(mtime), content p = re.compile(r'([\d.]+?) +([\w/]+)') def remote_mirror(src, dst): mtime, content = get_info(src) if exists(dst) and mtime == int(getmtime(dst)): return print 'update:', dst, src if not src.endswith('/'): open(dst,'wb').write(content) else: if not exists(dst): os.makedirs(dst) for mt,filename in p.findall(content): mt = int(float(mt)) lpath = dst+filename if not exists(lpath) or int(getmtime(lpath)) != mt: remote_mirror(src+filename, lpath) os.utime(dst, (mtime,mtime)) if src.startswith('http://'): mirror = remote_mirror else: mirror = local_mirror while True: mirror(src, dst) time.sleep(1)

如果源文件不在同一台机器上,可以通过NFS等共享过来。或者可以通过支持列目录的HTTP服务器来访问远程目录,mirror.py 已经支持这种访问方式。server.py 是用webpy做的一个简单的只是列目录的文件服务器。由于瓶颈在IO上,它的性能不是关键。server.py的代码如下: #!/usr/bin/python import os,os.path import web import time root = 'tmp' HTTP_HEADER_TIME = '%a, %d %b %Y %H:%M:%S %Z' class FileServer: def GET(self, path): path = root + path if not os.path.exists(path): return 404 mtime = time.localtime(os.path.getmtime(path)) web.header('Last-Modified', time.strftime(HTTP_HEADER_TIME, mtime)) if os.path.isdir(path): for file in os.listdir(path): if file.startswith('.'): continue p = os.path.join(path,file) m = os.path.getmtime(p) if os.path.isdir(p): file += '/' print m, file else: print open(path,'rb').read() urls = ( "(/.*)", "FileServer", ) if __name__ == '__main__': web.run(urls, globals())

为了获得更好性能,以达到更好的实时性,Hash Tree最好是平衡的,比如BTree。如果一个文件发生变化,同步它需要进行的IO操作为N*M,其中N为数的层数,M为每层的文件数目。现在我们N为2,M最大为10000,适当减少它可以获得更好的性能,比如N为4,M为100。在以后创建目录结构时,最好能够考虑这方面的因素。

之前hongqn推荐过一个利用inotify的文件同步方案,同步方式类似于mysql和bdb等,由于过于复杂导致不可靠而没有采用。上面这个方案只用了一百多行Python代码就基本解决问题了,是不是很帅?:-)

10:51 周末絮语:地球日;祈愿行;防骗术 » 大学小容>善用网络,助益成长!

今天对上周的周末絮语做了一些修改,将几句关于米国志愿者的看法加上了删除线,这表示小容写这些想法欠缺考虑。

在此,小容特别声明一下,这个blog只是记录个人的观察、感受和思考,并不能保证所有的文字都绝对的客观和精确。如果各位对米国的情况有更进一步的兴趣,小容建议大家阅读南桥的黑三角

1.

4月22日是地球日(Earth Day),小容去附近的超市用十个塑料袋换回了二个环保购物袋。超市在那天举行活动,而在平日则要用钱来买环保袋。下面是照片。

地球日的官方网站,地球日2008的活动网页。

大陆的blog服务商BlogBus.com也推出一项“我不是塑料袋”的环保袋设计竞赛活动。希望有更多的大陆企业加入到推广公益理念的行列中。

2.

QienKuen在半个月前在祈愿行(PledgeBank.com)创建了一个祈愿:

我将 拒绝一次性木筷和塑料袋,只要100个华语世界的人将 做同样的事情。
— QienKuen, 珍爱地球,珍爱生命 (联系)

签名截止期限至: 2008年06月01日

已经有18人签署, 还需要82人

详细内容:

一次性木筷给森林带来巨大的破坏和压力。导致森林资源保有量低、分布不均、质量不高、林地流失严峻,以及林木严重过量采伐。

所谓“一次性卫生筷”并不卫生,长期使用会对食道、呼吸道等来严重健康危害,引起哮喘等。

————————分割线————————

一次性塑料袋含有多种毒素,对人体危害极大。同时,一次性塑料袋严重污染环境。

小容看到这个祈愿的时候,没有立即去签名支持,因为祈愿行(PledgeBank.com)2008年的新版本网站有一个新功能,它会在祈愿成功之后提醒签名人是否真的履行了祈愿,小容真发愁每周去超市购物带回来的塑料袋如何处置呢。

好在上周就看到超市里关于地球日免费换发环保袋的活动,于是在周二特意去超市一趟。拿回环保袋之后,才去签署QienKuen的祈愿

当然,你不需要像小容这么做。因为如果QienKuen的祈愿如果没有招揽到100个人——换句话说,祈愿没有成功——你即使签名了,也不需要去实践祈愿。所以,请大胆签名吧!

你也可以帮忙Qien Kuen去宣传这个祈愿:)或者,你自己有什么好的想法,也可以在祈愿行上试一下,看看周围的朋友会不会响应。

另外,对祈愿行感兴趣的朋友,可以加入豆瓣上的祈愿行小组和大家交流。

3.

这周还收到一个老朋友的来信,讲她差点上当的故事,有个骗子打手机给她,说着说着,她差点认为那人是小容,那个骗子接着就说车祸的事,请求她打几千元钱给她。想要更仔细地看这个故事,请看这里

这个故事的启发是:

• 网络世界也可以建立友谊和信任

• 现实世界也有骗子

• 我们应该和朋友保持联络

• “订阅朋友的feed”是值得推广的防骗术

为了让“订阅朋友的feed”成为卓有成效的防骗术,请务必:

1、在你的blog里设置一个关于“生活”的分类或者标签,请务必每周更新一次这个分类。如果有重大事项,请务必及时在Blog上通告朋友。

2、同样,请在你的RSS阅读器里设置“朋友”这样一个标签,订阅他们blog的RSS地址,或者他们Blog里的“生活”分类的RSS。

现在小容还呆在米国,如果有人打电话给你说小容回国了,请不要上当受骗。

4.

周五的时候,附近的United Way在举办一个志愿者聚会,于是在中午吃了午饭之后走过去看,发现他们还在布置会场,后来傍晚下班了走过去看时,发现他们的聚会已经结束了。

中午的时候拍了几张会场桌面的照片,想看更多,请点这里

01:26 邮件讨论组之十:关于网络工具的场论2.0公式 » 大学小容>善用网络,助益成长!

上一次小容介绍了社会心理学家库尔特•勒温(Kurt Lewi)和他的场论,小容还尝试套用场论的公式发展出一个关于网络工具的场论2.0公式。

用户行为 = 函数{用户(需求×技巧×知识×态度×社交),工具(功能×界面×设置×安全×兼容)


在这篇贴子里,小容会结合这几篇贴子所讨论的Google Groups邮件讨论组,以及其他例子,对上面的公式做进一步的解释:

1、用户层面

·需求:

用户的确有这个需求。例如小容希望参与很多个邮件讨论组,能够很方便地和各个方面的人保持交流,至少可以获取各个方面的信息。而又希望能够很节省时间,所以Google Groups是比BBS更好的选择。当然,有时候这种需求不见得会附带上情感,用户仅仅是为了完成某项任务而已。

·技巧:

用户掌握了一定的使用技巧。例如使用Gmail来参加Google Groups可以获得最佳的用户体验。请注意,Google Groups支持多种电子邮件,并不是局限于Gmail用户。对于工具开发者来说,不应当一味去迎合用户的当前习惯,要放弃一些功能。因为随着时间的推进,用户的技巧会增强,这样迎合用户的做法就会限制产品的发展。

·知识:

用户了解这类服务,他只是挑选哪个品牌更好。例如,小容明确地知道邮件讨论组是什么东西,并不需要去看说明书才知道如何使用,只是在Yahoo GroupsGoogle Groups之间,小容选择Google Groups。如果一个用户不了解邮件讨论组的基本常识,在一个邮件讨论组里胡言乱语,不知所云,那么,他很快就会在邮件讨论组里成为大家讨厌的人,没有人愿意和他交流。

·态度:

用户是不是积极地使用,用户有没有将情感注入其间。如果是积极地使用,那么,用户就会将时间资源分配在上面。而且态度也会影响用户的具体行为,例如,小容知道Groups是很好的社交工具之一,就不会在邮件组里乱来,会遵守邮件组的礼仪,不会自说自话骚扰别人,单独的辩论也只会回复给所有人。用户在使用产品过程中感觉到愉悦的体验的话,他也会更加愿意使用这个产品,并逐渐将情感注入其间。

·社交:

用户的交际圈子对工具的选择也影响着用户的选择。一方面,用户希望自己和圈子里的朋友保持同样的特质,当一个用户他所在的圈子都使用Google Groups邮件讨论组的时候,那么这个用户也就不会经常去用BBS,因为他觉得自己用BBS会被圈子里的人认为是很逊的行为;另一方面,许多网络工具本身就是交流工具,交流需要双方参与,当一方转移到另一个工具上的时候,另外一方也会逐渐转移过来,否则交流就中断了。当用户的交际圈子逐渐从一个IM工具转移到另一个IM工具的时候,用户也会不由自主地加入这个浪潮。

2、工具层面

·功能:

能够帮助用户做什么事情,有什么好的方法让用户把这个事情做得更好。这个和用户的需求直接对应。例如Gmail的功能就是让用户使用电子邮件,而使用电子邮件已经是大家熟悉的网络服务,不过Gmail在发布的时候,做了一些在当时看来属于创新的功能,例如将同一个主题的多个回复安排成同一个会话,而不是零散显示。

有时候功能不仅仅是满足用户的需求,而也可以改变用户的行为。例如Facebookpoke功能,通过一个简单的动作,简化人们的沟通。这样的简化降低了用户的使用门槛,从而使得Facebook上的人际交互更频繁地发生。

·界面:

具体实现功能的布局、外观和交互流程。程序员通过写程序代码实现功能之后,用户还不能直接使用,代码还需要用户可以看得见的页面。这些页面的结构布局、视觉外观,以及不同页面的动作顺序和响应情况,这些就是通常所说的界面。如果代码很优秀,而界面很不友善的话,用户就不能达成他的任务,从而感到沮丧。

优秀的界面设计,带给用户愉悦的体验,用户在使用工具的过程中几乎不要思考,从而将注意力高度集中在任务本身,而不是在工具本身。试想一下,当我们用钢笔写一封信的时候,我们将所有的注意力放在写信这件事情本身,而不是钢笔上,

·设置:

工具开发者为功能提供了多个级别的选项,用户可以根据自己的情况来调节这些设置,让工具适应自己。小容在之前的贴子中详细讨论了Google Groups的接收模式设置和Gmail的过滤器设置。

当用户埋怨某个服务变得不好用的时候,他们应该先去检查一下工具的默认设置。许多用户从不更改这些默认设置,没有发挥出工具的最大效能。从这里也可以看出,工具的默认设置非常非常关键,这影响到新用户群的体验,也影响到工具未来的发展。

·安全:

这里所说的安全包括很多层的意思。首先,工具必须安全可靠、响应及时,不能隔三差五地出错;其次,用户的数据是安全的,他知道自己的数据不会轻易丢失,如果网站不能给用户这个信心的话,用户就不会投入地使用;其三,用户还会担心自己的安全,换句话说,他希望自己的隐私在使用工具的过程中是有保障的。

小容在整理自己的Google Groups的接收设置模式的时候,发现Google Groups邮件讨论组允许用户定义自己在每一个邮件讨论组里的用户名。这是一个非常尊重用户安全的细节。Google Groups邮件讨论组里是不会显示用户的具体电子邮件地址的,它使用省略后的电子邮件地址。换句话说,如果一个用户想要隐瞒自己的身份的话,他可以在不同的邮件讨论组里使用不同的用户名,这样别人不会把他在多个邮件组里的活动认为是一个人,因为从省略后的电子邮件地址上看不出来的。

除非用户自己在签名上加上名字和完整的电子邮件地址,除非用户自己去单一回复某个其他用户,除非用户在接收到其他用户发来的单一回复之后,也使用单一回复给对方……否则,一个用户可以安全地参与邮件组的讨论,而不用担心泄露自己的完整的电子邮件地址给管理员之外的其他人。

·兼容:

和用户层面的“社交”有些异曲同工,用户是和其他用户联系在一起的,同理,工具也是和其他工具联系在一起的,而且,这种联系,也会影响到用户的使用。

小容在这里先用“兼容”这个词来表示这种“工具间的联系”(或许“扩展”、“联系”、“开放”这些词会比“兼容”这个字眼更好)。

一个品牌的工具系统是否和另外一个品牌的工具系统兼容,会给用户带来很大的影响。例如,Google Groups兼容使用Gmail和其他的电子邮件服务,而不会局限在仅仅使用Gmail的用户群中;RSS阅读器可以让用户导出和导入OMPL订阅数据;BSP可以让用户导出和导入数据;1IM工具和其他的IM工具兼容。小容前一些时候体验到的一个反例就是Live的邮箱,小容想将一个Live邮箱设置成自动转发所有邮件到Gmail邮箱,结果是微软拒绝这个操作:)

这里的兼容还包括更多的含义,例如开放API。工具开放API,让第三方可以开发衍生应用,并用在其他工具上,而且工具本身也接受其他工具的API应用。

这里的兼容还包括母品牌绑定帐号的含义:例如Yahoo在收购了Flickr之后,将Flickr的帐号和Yahoo的帐号绑定,这让一部分Flickr的用户觉得气愤添膺。而在mybloglog里修改用户头像的时候,它会问我们是否将修改适用于所有的Yahoo系统(mybloglog.com也是Yahoo旗下的服务)。

如果你有任何批评和建议,请在这里留言,帮助小容一起完善这个公式。

系列回顾:

成群结对:形形色色的网络、群体和个体

前文回顾:

邮件讨论组之一:本地工作与远程工作
邮件讨论组之二:几个关键影响因素
邮件讨论组之三:几个关键影响因素(续)
邮件讨论组之四:半虚半实的IPO项目邮件讨论组
邮件讨论组之五:IPO工作组的项目管理诀窍
邮件讨论组之六:为校园活动创建邮件讨论组
邮件讨论组之七: 盘点你的Google邮件讨论组
邮件讨论组之八:Google Groups的接收设置和Gmail的过滤设置
邮件讨论组之九:行为与环境,控制与赋权

准备尝试p2p的个人小额贷款Herock Post » Che, Dong's shared items in Google Reader

kiva  有朋友说他正在参与陕西的一个微型贷款项目,说是类似kiva的模式,回来后碰巧看到Richy也写到賀!Kiva放款客戶超過20組!,我这才发现kiva将一个很好的想法变成了现实。

  kiva的运作建立在“microfinance”的理念之上:

Microfinance is the supply of loans, savings, and other basic financial services to the poor.

  发现豆瓣的这篇帖子介绍的非常详细,觉得kiva的妙处在于:

  1. 参与方便,行善毕竟是帮别人的忙,总不希望自己太过操劳,能在线完成一切,是很重要的。
  2. 成果可监控,对大部分人来说,帮助别人其实是能让自己获得内心满足的途径,只要确定资金没有被滥用,且可以看到自己投入的金钱或精力究竟起到了什么样的效果,就会很主动的去做。
  3. 最重要的一点,这不是捐款,而是免息放贷,目前99%以上的还款率,基本上能保证你可以达到帮助了别人,自己也不受损失的效果。

  广州一帮朋友,曾组织到广东贫困山区定点扶助那里的学生,每人认领几个,负责他们的学费,这种纯手工的做法,资金的安全性挺高,效果也可以随时跟踪,但毕竟操作成本还是过高了,不宜大规模开展。而在技术的帮助下,kiva的整个流程已经高度透明化且有效率,非常有助于提高个人投资者的热情和信心,关键点应该是落在MFI上:

A microfinance institution (MFI) is an organization that provides microfinance services, ranging from small non-profit organizations to large commercial banks.
就像陕西的那个项目,“最后一公里”也是需要和当地的妇联合作,如果MFI或妇联做的不够公正和高效,则整个系统的效果将大打折扣。

  不过即使如此,我也觉得比希望工程之类的,要可靠的多,已经注册了kiva的帐户,paypal上还有些散碎银两,本来想给flickr续费的,但该死的flickr貌似不支持paypal付款方式了,刚好尝试用来做做善事。


^==Back Home: www.chedong.com

^==Back Digest Home: www.chedong.com/digest/

<== 2008-04-27
  四月 2008  
  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30        
==> 2008-04-29