Monthly Archives: 05月 2011

Redis点滴

最近试验在产品中使用Redis来完成以前MongoDB做的一些工作,发现在大量消息采集的场景下(咱们这次不谈查询什么的),redis比mongoDB表现更好──这里主要是指编程更简便、逻辑更清晰。下面我举一些小例子说说Redis都为我们解决了什么问题,技术上下文关键字:高并发、分布式。 插入与更新操作的无差别性 Redis的所有SET(包括MSET,HMSET)操作都是:存在则更新,不存在则插入,即insert if not exists。所以在编程的时候开发人员不需要关心所做的操作属于更新还是插入,减免了判断,因此也避免了判断操作可能带来的锁定。 MongoDB也有同样的操作,update操作的upsert参数调为True即可,不过经过测试,MongoDB为查询条件为了索引后使用update with upsert来代替insert操作,效率比光insert要低5倍以上,而redis的HMSET操作的效率要胜出。 GETSET的妙用 上一个经验虽说可以解决这条数据该“插入还是更新”的问题,但需要知道当前操作是否针对某数据的首次操作的需求还不少。例如我的程序会在不同时间接收到同一条消息的不同分片信息包,我需要在收到该消息的首个信息包(发送是无序的)时做些特殊处理。 早些时候的做法是为消息在MongoDB维护一个状态对象,有信息包来的时候就走“上锁->检查消息状态->根据状态决定做不做特殊操作->解锁” 这个流程,虽然同事已经把锁的粒度控制得非常细了,但有锁的程序遇上多实例部署就歇了。 Redis的GETSET是解决这个问题的终极武器,只需要把当前信息包的唯一标识对指定的状态属性进行一次GETSET操作,再判断返回值是否为空则知道是否首次操作。GETSET替我们把两次读写的操作封装成了原子操作,V5啊。 山寨版数据过期策略 我曾经想过要写服务器端的脚本来扩展redis,试图要拿到数据过期的事件,用来做一些回调来处理过期数据,但很快我发现这个不现实。于是我选择通过使用排序集合(SORTEDSET)来实现一个山寨的数据过期策略:需要定时过期的数据,统一添加到一个排序集合:ZADD expiringKey timestamp data。在这里我使用了时间值(毫秒为单位的长整型)作为数据的分数,那么很自然的,早期的数据总会排在集合前面;然后我写一个程序会定时地过来打理这些过期的数据就好了。 存储结构化数据 例如有“通讯录”这样的数据,包含有”name”,”city”,”gender”等8个属性,使用mongoDB保存就很简单,创建一个Document,设置属性后存储即可,而Redis本身并非Document型的DB而是Key Value DB,要存储这种数据,还得在Key上面花一点功夫:使用contact:id:name,contact:id:city,contact:id:gender之类的Key来存储其对应的值。当然,这只是使用redis存储结构化数据最原始的办法,更建议的办法是使用Hash存储,如 hmset contact:id name jeff contact xx@gmail.com gender male。相对set操作而言,hmset既节省了存储空间又提高了存储效率。 使用MongoDB来存储这些数据是小菜一碟,但鉴于第一点经验,我还是愿意使用Redis。 比较可惜的是,目前Redis的Hash存储仅支持字符类型的值,不支持其他数据结构,我非常期待它日后会支持其他数据结构,甚至支持Hash的嵌套。关于这点,@wuvist 同学认为十分有可能。 小结 上面这些Case都只是Redis牛刀小用,但实际上给程序带来的便利是非常明显的,最明显的就是可以把原来的程序上使用的锁都抛弃掉,甚至直接支持分布式运行和水平扩展了。 顺便在此小结一点高并发分布式应用程序编写的一些推荐的注意事项吧,当然这是我的个人偏好并结合了一些特定业务领域的性质: 1. 程序对资源最好是只读或只写,明确分工。不要在一个程序里同时对资源进行读写,除非是原子操作,如GETSET。 2. … Continue reading

Posted in 技术 | Tagged , , , | 3 Comments

Autoforms使用指南

Autoforms是Jeff开源的一个基于Django的自定义表单引擎,可用于调查、投票、信息收集甚至是整合至工作流程引擎和PAAS平台当中。目前AutoForms主要用于支持珠三角地区几个技术社区的线下活动报名、反馈收集等。jeff在本站上也搭建了一个autoforms的实例,可以免费为大家提供简单的在线表单服务,有兴趣者,可联系我开通帐号。最近对AutoForms的使用反馈越来越多,所以更新会相对频繁一些,嗯,有人使用就有动力呀! AutoForms(今天下午发布最新版本为0.4)的主要特性: 支持14种字段类型13种html输入控件(包括日期选择组件),可以快速定制大部份常见的表单。 保存用户提交的表单数据,并向表单作者展示,同时提供数据导出功能。 支持表单继承,需要周期性地使用相同的表单时,一点也不费力。 用户填写表单后,邮件通知表单作者。 提供了丰富的API,容易与其他应用程序作整合。 关于AutoForms的安装请参考github上面的说明,本文主要的内容是指导表单用户如何使用Autoforms。 登录 首先登录至管理界面(http://f.jeffkit.info/admin/ 帐号为 form/form),会看到Autoforms的应用,该应用有两个模型可供管理: 表单管理提供快速创建、修改表单;预览表单,查看表单数据以及生成某入式表单代表等功能。 表单域管理则提供对某些表单域的高级设置功能。 创建表单 下面我通过创建一个“AutoForm用户反馈表单”为例,示范一下如何使用AutoForms来创建表单。 首先,我们点击表单管理的增加按钮开始,打开增加表单的页面,表单上半部份是表单的基本信息,下半部分是定义该表单所包括的字段(表单域)。下图是填写AutoForm用户反馈表单的示例数据: 补充说明一下上面页面一些容易迷惑的地方: 父表单:如果指定某个表单为父表单,那么所创建的表单将自动获得父表单的所有字段。 启用:如果处于勾选状态,则表单可供填写,否则表单只能查看而不能提交。 表单域里的组件:组件是指在页面上展示表单时使用的HTML控件,如你的字段是密码类的,你最好选择“密码输入框”组件。一般情况下,使用默认的组件已经足够。 接下来,点击”保存并继续编辑”按钮,这时在页面的面上角出现了一些快捷按钮: 预览,让您预览所创建的表单的展示效果。 数据,用户通过表单提交数据后,表单作者可以在此看到所有提交的数据并可将数据导出为CSV格式。 嵌入,autoforms允许用户通过嵌入页面的方式展现在第三方网站上面,点击该按钮可获得嵌入的HTML代码。 历史,Django的内置的数据为更记录。 在网站上查看,点击后打开填写表单页面。 预览表单 我们先点击预览按钮,看看刚才创建的表单的效果如何!结果有点意外,“评分”和“在哪了解到autoforms”两个字段光秃秃的! 其实并不意外,我们在表单是创建了两个选项/多选值类型的字段,而我们还没有为这两个字段提供选项数据,所以它们看上去是光秃秃的,那么下一步,我们就是要为选项类型的字段加上选项数据。 编辑字段 返回管理首页,点击表单域进入表单域列表页面,在这里可以找到刚在才创建表单时生成的几个字段,点击“在哪了解到autoforms”进入该字段的编辑页面,页面由一个展开区域和(字段基础信息),三个隐藏区域(高级设置、选项、错误信息)组成。高级设置暂略过不理,选项区就是我们要为选项类型的字段提供数据的地方,而错误信息则允许我们自定议错误提示内容。 下面我要为“在哪了解到autoforms”字段提供一些选项数据,如下图这般添加一些数据: 保存字段的修改,再依法泡制一下“评分”字段,一个表单就完成了。最终结果就是下面的表单了,各位使用过autoforms的同学,来这里给我一些建议吧。 收集数据 表单定义好了,是时候发出去给大家填写了,收集上一段时间后,可以通过“数据”页面来查看已经收集好的数据,如果你愿意,可以点击右上角的导出按钮,以CVS的格式导出数据: 好了,AutoForms的基本使用就这么一些,如果你是开发人员,对API感兴趣,欢迎阅读代码,如果你有些空闲时间,希望掺和一些开源项目,AutoForms也欢迎你加入到开发者行列。

Posted in 技术 | Tagged , , , | 7 Comments