一起租块地种稻花香大米吃

每天在城市生活,想吃到新鲜原生态的食材却越来越难。我在黑龙江长大,很怀念小时候米饭的味道,却很多年没再吃到过。前段时间偶然回东北老家,吃到了久违的稻花香米,满屋飘香,让我忽然有了个想法,能不能和身边的朋友一起,去租一块稻田,让有经验的老农用传统方法帮我们种植最纯正最绿色的稻花香大米。

稻花香大米产地是黑龙江五常,1853年起,皇帝命五常地方官每年派专人负责监种、监收,岁岁进贡大米,得名“五常贡米”。现在也是中国国宴用米。因为口感香甜和营养丰富,民间有“一餐五常米,浑忘酒肉香”之说。五常是个水稻大市,单季水稻面积和产量均居全国县市之首,是国家百万亩绿色水稻种植基地。即便这样,五常大米如果供全国人吃,每人每年也只能吃到一碗。

稻花香米细长,表面有油光,晶莹剔透。米饭筋糯宜口,清淡略甜,松软劲道,营养丰富。剩饭不回生,冷却后仍能保持良好口感。我计划租种的稻田在黑龙江五常稻花香米核心种植区民乐朝鲜族乡,打算采用古法种植,施农家肥,人工除草,人工收割,收成后不脱壳存放,现磨现发货,以保证粒粒香,粒粒真,做到比日本越光米更糯,比泰国香米更香。

目前已确定租种五常金粟水稻种植基地的农田,请他们按照我们的要求来种植正宗的稻花香2号大米,全程不用化肥,绿色无污染,下个月开始插秧,秋天收获后不脱壳,只存放稻谷,然后每个月磨一次米配送给入伙的各位,并且磨米时保留部分胚芽,这样的米最新鲜,也最大程度的保留了营养成分。从插秧开始,我会不定期上传基地图片,各位入伙后有兴趣也可以去当地参观采风,去看看我们那绿油油的水稻田,还可闻到淡淡的稻香。

【入伙方式】:每人缴纳2000元作为入伙资金,可获得够全家一年吃的300斤好吃原生态的稻花香大米。由于租地的面积原因,产量有限,因此入伙人数有限制,先来先得。入伙资金可直接汇入我的支付宝账号:

9155091@qq.com

也可用手机支付宝客户端扫码支付:

apw5x3e398dq6cbq15

入伙后可以加我的微信交流:imbanping,我会第一时间通报水稻生长进度。

【磨米方式】:收成后保留稻谷,也就是从田里脱粒回来的水稻果实,然后每一到两个月在附近的磨米厂把稻谷磨成大米,磨米过程中不会像工业化大规模生产那样抛光色选,而是要最大限度的保留稻谷胚芽等原始营养元素,不但吃的新鲜,而且有粗粮的功效。

【配送方式】:由于我大部分参与本项目的朋友在厦门,所以每一到两个月会统一物流运到厦门,届时我会找个地方存放,自提,也可以承担同城物流费用由我安排送米上门。不在厦门的朋友,统一物流或快递发货,需要自己承担每次的运费。

【价格说明】:本次入伙产出大米的折算价格大概是6.66元一斤。同样品种但是工业化生产出来的不新鲜的稻花香大米,在外面卖15元左右一斤。本次一起租地种大米的成本大概如下:

【种植环节成本】:
稻谷:2.4元/斤
全程种植监管:0.1元/斤
仓储、维护:0.1元/斤
谷仓至磨米厂运费、人工、包装材料:0.1元/斤
稻谷成本合计:2.7元/斤

【加工环节成本】:
大米:5.3元/斤(稻谷2.7元/斤,按平均出米率51%折算)
磨米费:0元(用稻糠、碎米相抵)
大米包装人工费:0.15元/斤
大米包装材料费:0.15元/斤
基地至厦门运费:0.4元/斤(厦门之外的朋友,这部分费用由我承担)
大米成本合计:6元/斤

我和我在当地帮忙看管种植的朋友获得的毛利:0.66元/斤(按10%毛利率计算)

最终大米价格:6.66元/斤

相同的纯正稻花香米价格对比:

屏幕快照 2014-04-16 下午8.29.39

难得糊涂

人生是令人费解的。

从懵懂的孩子,到慢慢的了解这个世界,长大的过程,也是我们老去的过程。

青春太美了,所以不可能没有遗憾。无论你做什么,都会留有遗憾。因为,在那短短的时光里,你不可能穷尽所有的生活方式。

我们慢慢的了解了世界,却仍然不了解自己。

我是为何而生活,为何来到这个世界上,为何承受着生活的苦难,却无力自拔和不去改变?这是应有的人生状态吗?

《红楼梦》说,满纸荒唐言,一把心酸泪,都云作者痴,谁解其中味?

高人说,难得糊涂,得过且过,认真,你就输了。问题是,糊涂,是多么难以做到啊!已经说了难得了,就是没有一定修为的凡夫俗子是做不到的,既然做不到,就会认真,就输了,所以会痛苦。

多年来,一直生活在理想主义的状态里,以为人生经历的一切都是要完美的,即使偶有瑕疵,也能够瑕不掩瑜,安静平顺的度过。并为此隐忍退让,随遇而安。

当我渐渐的长大,开始去探寻人生的意义,开始想人生的价值所在。

人,为了什么而生活?有多少人在这个世界上追逐着名利,精神和物质,可是功名利禄也终究是一阵烟,死去后万事皆空。而在这追逐的过程中,又有多少是我们内心的真实想法呢?

追寻自己的内心,观察和体验这来了一次的世界。

最怕的,是在回首来时路的时候,内心充满了遗憾。深深的遗憾!

真心,真难。

书店的倒掉

很久没有在线下的书店买书了,以至于想去买书的时候,我在努力寻找哪里还有书店,除了红色的新华书店,还有没有可以去的地方。之前卖咖啡的光合作用已经很可惜的倒掉了。

这次要去线下书店,是因为在线上买来不及了,不是那个徐小平要来嘛,想买一些书请他签名回馈参加创业周末厦门站活动的朋友,所以只能去线下书店搜罗,找了几家书店,最终搜集到12本书。

说说我在外图书城的经历吧,先看看营业时间,我在9点到的时候,才知道营业时间是9:30到21:30。而原想生意冷清的书店竟然也门庭若市。

然后等到9:30开门,进去后一楼是服务台,二楼是收银台,经管类图书都在二楼,于是上楼,可悲的是电梯竟然是坏掉的,要走自动扶梯上楼。

上得楼来,我要找徐小平的书在哪啊,想找自助查询机,发现还没开机,尼玛,9点半了还没准备好,你们的工作人员都是干嘛的?就这样也能开门接客?抓来个工作人员来开电脑,于是就站在这里等待,寂寞的等待:

开好机,查到了位置,找到了11本书,这个书店里徐小平的全部藏书,都被我打包买走了。

去收银台买单,一点折扣都没有,尼玛,怎么和网络书店竞争呢?不过收银员很聪明的建议我先去办张会员卡,会员卡能打9折,算下来能给我节省38元,而办卡的费用是30块,也就是我现在办卡能省8块。以后还能一直享受9折优惠。那一刻我犹豫了一下,说实在的,我很清楚知道以后很难有机会再在线下书店里买书了,而且办卡要跑到一楼服务台去办。但是为了8块大洋,还是蹭蹭蹭下楼来了。

到了服务台,填好单据,毕恭毕敬的递给服务员,同时递上我的那张用了好几年的建行黑色的信用卡,服务员说,请交30块现金,我们服务台不能刷卡。我说没带现金,服务员说那就不能办。于是我装作正派面带笑容的把单据撕得粉碎,又蹭蹭蹭的从自动扶梯爬到二楼去买单提书。

现在,这些《图穷对话录》安静的坐落在我的桌子上,等着徐小平签名,而我想的是,那些线下书店的倒掉,难道不是咎由自取吗?

Sphinx重建索引失效案例分析

重建Sphinx索引的时候,可以使用以下命令:

/sphinx/bin/indexer –rotate idx_name

但是这个命令并不是保证一定能重建成功的,有时候重建了之后,发现新的数据并没有加入到索引里,而从日志可以看到这样的记录:

WARNING: rotating index ‘idx_m_tag’: lock: failed to lock /sphinx/data/idx_m_tag.new.spl: Resource temporarily unavailable; using old index
WARNING: rotating index ‘idx_n_tag’: lock: failed to lock /sphinx/data/idx_n_tag.new.spl: Bad file descriptor; using old index
[Sun Mar 24 06:40:01.084 2013] [12413] rotating finished

日志记录了重建索引失败,继续使用旧的索引这一事实。

要分析这个原因,首先要知道sphinx的重建索引的流程,日志里记录的spl文件,实际是一个空文件,只是sphinx加锁的一个标记而已。重建索引时,会生成新的索引文件,即在原来的文件名字后面加上.new标记为新文件,旧文件不变。然后重启searchd进程,所以我们在执行rotate index的时候会看到这样的输出:

rotating indices: succesfully sent SIGHUP to searchd (pid=12413).

searchd进程启动后,会执行一个操作,把旧文件命名为.old文件,把.new文件更新为正常的索引文件名,如果有问题,会有 一个回滚的操作。在这个过程中,通过对spl这个文件的加锁和解锁来进行文件切换。

如果对spl的锁争用出现问题,就会导致新的索引文件不生效,这时候的解决办法是手动重启searchd进程。

如何避免这个问题,最简单的就是对sphinx日志进行监控,通过脚本捕捉到lock spl文件失败的情况,马上处理。

语音文件转码—适应手机和网页播放

移动互联网时代,语音越来越成为移动应用的主流,手机上一般是amr格式的文件,如果这些文件要在网页上播放,一般需要转换为mp3格式,如何转换?本文介绍一个开源工具——ffmpeg

要支持mp3输出,首先需要安装一个lame包,下载地址如下:http://lame.sourceforge.net/download.php

ffmpeg的安装也比较简单,首先下载源码包,然后在配置的时候指定如下参数:

./configure –enable-libmp3lame

接下来make & make install就可以了。

ffmpeg提供了一个命令行工具,可以直接转换:

ffmpeg -i 1.amr 1.mp3

应用程序可以调用命令行实现文件转换的功能,比如java里调用方式如下:

String command = “ffmpeg -i /tmp/1.amr /tmp/1.mp3″;

Process process = Runtime.getRuntime().exec(command);

如果文件存储在mogilefs分布式系统里,可以使用mogtool命令来实现文件的读取和写入,mogtool要运行需要以下两个包的支持:

MogileFS-Client-1.14

IO-stringy-2.110

读取和写入的命令如下:

mogtool --trackers=192.168.0.27:7001 --domain=voice --class=tui extract 1.amr /tmp/1.amr

mogtool --trackers=192.168.0.27:7001 --domain=voice --class=tui inject /tmp/1.mp3 1.mp3

提供一种思路,希望分享给需要的人。

别了,2012!

goodbye,2012!

hello,2013!

年终总结最常见的一句话就是“过去的。。。年,是不平凡的一年”,这句话对也不对,因为每一年都有很多事情息生,是不平凡的,而放在历史的尘埃里,不过是白驹过隙,微不足道,平淡无奇。

于是就这样懵懂,长大,感悟,和老去。

如同青春岁月,在不经意间忽然的离你而去,你甚至来不及主动的发出一声叹息,留下一些记忆。

今天阳光温暖,但是气温很低,房间里很暖,外面很冷。而内心的温度,实际是和环境无关的。

早上很早起来,每天都很早起来。一路上斑驳的树影遮挡了阳光的照射,开车走在这城市的路上依旧拥挤,让我想到一个词:恍如隔世。

本来想去附近的邮局把一个挂号信取了,结果说时间太久被退回去了,超过了1个月没取就会退回去。也不知道是谁发的什么信,或许这也说明了我生活的懒散,亦或忙碌。挂号信不靠谱,太麻烦了,还不如发到信箱的广告传单好,至少能送达无误。

去医院把9月份的体检报告拿了回来,还是一堆不正常的指标,随着年龄的增大,这些对于我来说,已经感觉麻木了。我想主要是酒,还有缺少锻炼了。我想这也说明了我生活的懒散,亦或忙碌。

中午和81、麻婆去夏商营养餐吃面,暖了身体。在这南国的这样的一个冬季。

过去的不说也罢,我想经历的都是财富,不管未来会如何,重要的是,我们共同经历了怎样的一段岁月。

人生会没有遗憾吗?不会没有,唯有内心的强大,才能永远的立于不败之地。这个观点很唯心吧。

如同上次在友南的婚宴上我说的,世界上没有因果,因为因,是错综负责的综合体,而这综合体,用我们苍白的语言和幼稚的逻辑,根本是无法描绘出来的。

热推,行业,O2O,移动,产品,技术,大环境,落地,明年继续在梦想的道路上挣扎,痛并快乐着。

我想,重要的是,在未来的某年某月某一天,我们在今天的点滴故事,可否成一段难忘的记忆。

没有痛彻心扉,却会有热泪。

———————————————————————————

半瓶

2012-12-31

岁末 于 小黑屋。

修改innodb_flush_log_at_trx_commit参数提升insert性能

最近,在一个系统的慢查询日志里发现有个insert操作很慢,达到秒级,并且是比较简单的SQL语句,把语句拿出来到mysql中直接执行,速度却很快。

这种问题一般不是SQL语句本身的问题,而是在具体的应用环境中,由于并发等原因导致的。最可怀疑的地方就是在等待表级锁。

加上监控的日志来看,很多SQL是在同一时间完成的,下面的第三列是结束时间,第四列是开始时间:

14:27:30 bizId30905 1355812050  1355812045
14:27:30 bizId28907 1355812050  1355812043
14:27:30 bizId30905 1355812050  1355812047
14:27:30 bizId17388 1355812050  1355812040
14:27:30 bizId40563 1355812050  1355812044
14:27:30 bizId15477 1355812050  1355812048
14:27:30 bizId32588 1355812050  1355812048

但是通过应用的分析来看,并不存在表级锁的地方,而insert自身的操作也只是对要插入的记录本身加锁,不会影响其他并发的insert操作。

没有更好的办法,只能在MySQL写入磁盘的性能上考虑,MySQL有个innodb_flush_log_at_trx_commit参数,用来配置flush log到磁盘的时机,具体点说,是从log buffer写到log file,并写入到磁盘上的时机。这个参数的默认值是1,即每次事务提交的时候会把日志刷到磁盘,而频繁的insert操作就会引起flush log操作的不断积累,进而引发性能问题。在应用数据可接受的前提下,可以把这个值改成0,就是每秒才操作一次。修改后潜在的问题是,在事务已经提交的情况下,如果尚未写入磁盘的时候发生故障,可能丢失数据。

MySQL官网对此参数的描述如下:

If the value of innodb_flush_log_at_trx_commit is 0, the log buffer is written out to the log file once per second and the flush to disk operation is performed on the log file, but nothing is done at a transaction commit. When the value is 1 (the default), the log buffer is written out to the log file at each transaction commit and the flush to disk operation is performed on the log file. When the value is 2, the log buffer is written out to the file at each commit, but the flush to disk operation is not performed on it. However, the flushing on the log file takes place once per second also when the value is 2. Note that the once-per-second flushing is not 100% guaranteed to happen every second, due to process scheduling issues.

The default value of 1 is required for full ACID compliance. You can achieve better performance by setting the value different from 1, but then you can lose up to one second worth of transactions in a crash. With a value of 0, any mysqld process crash can erase the last second of transactions. With a value of 2, only an operating system crash or a power outage can erase the last second of transactions. InnoDB‘s crash recovery works regardless of the value.

其他角度的优化办法:

如果是MyISAM存储引擎,可以使用insert delay的方式来提高性能,其原理是MySQL自身会在内存中维护一个insert队列,在实际表空闲的时候insert数据。

从应用的角度,批量提交也是解决问题的办法,当然要在应用场景许可的前提下。

管理MySQL数据的一些SQL小技巧

MySQL针对多表数据的DML一般比较低效,特别是in语句,大数据量下基本就不能使用,一般关联多表情况的增删改可以用类似如下的SQL来实现,当然,这种复杂的SQL在应用程序里是应该尽量避免的。列举几个小例子:

delete a from ta a, tb b where a.fid=b.fid and a.fls_id=b.fls_id;

update ta a,tb b set a.name=a.uname where a.uid=b.id;

update ta p,(select feed_id as id,sum(c) as c from ta group by feed_id) c set p.co=c.co where c.id=p.id;

update user u,tc c set u.username=substring(u.username,1,instr(u.username,’(‘)-1)
where u.id=c.id

在Oracle中,表连接有NL(Nested Loop)、HJ(Hash Join)和SMJ(Sort Merge Join)等方式,而在MySQL中,只有NL一种方式,所以就是拿驱动表的结果集做循环,去另外一个表里查数据。

另外,保证被驱动表的条件有索引很重要,一般被驱动表比较大,没有索引的查询会非常慢。

在MySQL的存储过程里使用动态SQL

MySQL的存储过程不好用,一般在应用开发过程中不建议使用。但有时候在数据迁移等环境中,特别涉及到复杂点的逻辑处理,就需要存储过程的配合了,当然,用其他语言写程序实现也是可以的,不过效率估计没有直接在数据库中操作高。

有时候数据所在的表是不确定的,需要根据实际情况临时决定表名,这时候就是动态SQL的用武之地了,以下示例展示了在一次数据导出的过程中使用动态SQL的存储过程例子:

delimiter //
CREATE PROCEDURE `proc_rt_imp_group`()
BEGIN
DECLARE done INT DEFAULT FALSE;
declare v_tid,v_ptable int;
declare v_tablename VARCHAR(32);
DECLARE cur_t CURSOR FOR select t.tid,t.ptable from pw_threads_rt t;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;

OPEN cur_t;
read_loop: LOOP
FETCH cur_t INTO v_tid,v_ptable;
IF done THEN
LEAVE read_loop;
END IF;
if v_ptable=0 then
set v_tablename = ‘pw_posts’;
else
set v_tablename = concat(‘pw_posts’,v_ptable);
end if;
set @updatesql =CONCAT(‘insert into pw_posts_rt select * from ‘,v_tablename,’ where tid= ‘,v_tid);
PREPARE sqltext from @updatesql;
execute sqltext;
END LOOP;
CLOSE cur_t;
END//
delimiter ;

使用Linux管道批量删除Redis的key

Redis并没有提供批量删除记录的方法,这有时候很不方便,特别是重新初始化数据的时候。一般有两种做法:

如果业务场景明确,可以通过DBID进行区分,Redis默认的DBID是0,默认的配置文件是有16个DB,可以在应用中通过select方法指定数据库的ID进行存取。然后通过FlushDB命令能清空某个ID的数据库,达到重新初始化的目的。

如果某个ID的数据库已经有很多类型的记录了,无法整个库清空,那么就需要批量的删除key值,这时可以采用Linux管道,比如我要删除DBID为1的test开头的key值:

[root@banping redis]# /banping/redis/src/redis-cli -n 1 keys “test*” | xargs /banping/redis/src/redis-cli -n 1 del
(integer) 5095

把keys的输出作为del的输入,这样就批量删除了。

附redis-cli 命令:

redis-cli 2.4.2

Usage: redis-cli [OPTIONS] [cmd [arg [arg ...]]]
-h Server hostname (default: 127.0.0.1)
-p Server port (default: 6379)
-s Server socket (overrides hostname and port)
-a Password to use when connecting to the server
-r Execute specified command N times
-i When -r is used, waits seconds per command.
It is possible to specify sub-second times like -i 0.1.
-n Database number
-x Read last argument from STDIN
-d Multi-bulk delimiter in for raw formatting (default: n)
–raw Use raw formatting for replies (default when STDOUT is not a tty)
–latency Enter a special mode continuously sampling latency.
–help Output this help and exit
–version Output version and exit

MySQL的wait_timeout参数太小导致表级锁失效

如果想让某个表只读不能被修改,可以在MySQL Server层面加表级锁:

mysql> lock tables sms read;
Query OK, 0 rows affected (0.01 sec)

然后其他的连接去更新或插入数据是不会成功的:

mysql> insert into sms(id) values (555);

因为要等待表级锁的释放,可以通过processlist看到这一点:

mysql> show processlist;
+——–+————-+———————+—————+———+——+——————————————-+—————————————–+
| Id | User | Host | db | Command | Time | State | Info |
+——–+————-+———————+—————+———+——+——————————————-+—————————————–+ |
| 364733 | root | localhost | banpingdb | Query | 0 | NULL | show processlist |
| 364734 | root | localhost | banpingdb | Query | 148 | Waiting for table level lock | insert into sms(id) values (555) |
+——–+————-+———————+—————+———+——+——————————————-+—————————————–+
2 rows in set (0.00 sec)

当然,更详细的信息也可以看到:

mysql> show engine innodb status G
————
TRANSACTIONS
————
Trx id counter 5AA0D8A
Purge done for trx’s n:o < 5AA0D77 undo n:o < 0
History list length 1063
LIST OF TRANSACTIONS FOR EACH SESSION:
—TRANSACTION 0, not started, process no 21967, OS thread id 1286076736
mysql tables in use 1, locked 1
MySQL thread id 364734, query id 3527582 localhost root Waiting for table level lock
insert into sms(id) values (555)
—TRANSACTION 0, not started, process no 21967, OS thread id 1284471104
mysql tables in use 1, locked 1
MySQL thread id 364733, query id 3527604 localhost root
show engine innodb status

但是,今天奇怪的发现,在等待了一段时间后,insert语句竟然莫名其妙的成功了,分析了一下原因。并没有什么地方控制表级锁的超时,就是因为表级锁被释放了,才能使得insert成功,而表级锁被释放的源头就是wait_timeout参数,这个参数的意思是:

The number of seconds the server waits for activity on a noninteractive connection before closing it.

如果这个值设置的小,比如说一分钟,那么一分钟后,不活动的连接就会被释放,而连接的释放会导致这个连接发出的表级锁被解锁。如果你的系统里这个参数很小,下面的这些信息一定是你经常看到的:

ERROR 2006 (HY000): MySQL server has gone away
No connection. Trying to reconnect…
Connection id: 364743
Current database: banpingdb

这个错误提示的就是连接超时了重新连的意思。
还有另外一个参数是interactive_timeout,是针对interactive connection的超时时间,但是在global层面设置这个值会引起wait_timeout的连带改变。

如何在mac下长期使用SecureCRT

SecureCRT是一个优秀的收费的工具,一个License貌似是99美金。但是不少人不愿意花钱买软件使用,于是破解大行其道。

Windows下的破解版很多了,但是Mac下貌似很少,搜了一下,在网上找到一个可用的针对6.7.3发破解版,过程如下:

一、首先去官网下载SecureCRT 6.7.3 for mac 版本。

二、去一个热心网友的网站下载patch。

三、执行以下命令:

sudo chmod -R 777 /Applications/SecureCRT.app/Contents/MacOS

四、运行patch程序,点击select Application选择已经安装好的SecureCRT.app,等待Patch完成。

五、使用补丁内附带的序列号注册即可。

六、如果无法保存密码,在SecureCRT的Preferences选择Terminalx下的Advanced,把Mac Options选型的Use KeyChain打勾去掉。

本人并不推荐使用破解软件,如果想省钱,可以使用替代方案,比如iterm2。

如何使用Amazon的邮件服务SES

云服务提供商Amazon有一项邮件服务,叫做SES(Simple Email Service),如果不想搭建自己的邮件系统,使用这个服务是很不错的一个选择。本文记录如何使用这项服务。

首先需要去Amazon AWS注册一个账号,然后就可以使用这项服务了,首先需要验证几个邮箱进行测试用,可以是用PHP或者Java、Perl等语言编写程序发送邮件,测试完成后,就可以申请转到生产环境,审批申请的时间是一个工作日内,具体官网上都有介绍,比较简单。

SES提供了三种API方式进行交互,一种是SendMail,一种是SendRawMail,还有是传统的SMTP方式,可以按需使用。

如果使用JAVA和SES通信,需要使用官方的SDK,即aws-java-sdk-1.3.5.jar这个包,还需要Apache的httpclient包,也就是httpcore-4.1.4.jar和httpclient-4.1.3.jar这两个jar包。

在测试过程中发现SES代发的邮件会被一些邮件服务商评断为垃圾邮件,进入了垃圾箱,比如163。为了解决这个问题,可以给邮件服务增加SPF、SenderID和DKIM验证,测试证明前两者基本被163忽略,而能解决问题的就是DKIM,有了这个DKIM,Gmail在显示邮件信息的时候甚至会把默认出现的amazon代发的头部信息去掉,很棒。关于DKIM,我以前的一篇文章曾经介绍过,不过那是和Postfix整合的,这次是要通过应用程序来调用,要注意的是,使用DKIM功能必需使用SendRawMail接口来发邮件。

增加SPF和SenderID的方法就是在DNS上增加以下TXT记录:

v=spf1 include:amazonses.com ?all

spf2.0/pra include:amazonses.com ?all

增加DKIM功能,需要先生成密钥:

[root@dev banping]# openssl genrsa -out banping.private 1024

[root@dev banping]# openssl rsa -in banping.private -out banping.public -pubout -outform PEM

然后把public key添加到DNS记录里:

 主机记录:s1._domainkey.mail

内容:k=rsa;t=y;p=……(public key内容)

对于如何使用private key进行签名,可以使用Apache James项目提供的一个包JDKIM,需要apache-jdkim-library-0.2.jar、apache-jdkim-mailets-0.2.jar、apache-mime4j-core-0.7.jar和apache-mime4j-dom-0.7.jar四个JAR文件。

特别要注意的是,JDKIM不能使用原始的Private key,必需经过格式转换和编码,我今天大部分时间都花在了处理这个问题上,因为官方文档并没有说这些,或者说了我没发现,后来看JDKIM的源码才发现了问题所在:

[root@dev banping]# openssl pkcs8 -topk8 -inform PEM -in banping.private -outform DER -nocrypt -out rsapriv.der

[root@dev banping]# base64 rsapriv.der

把base64转码后的输出作为private key参数传给JDKIM的对应函数就可以了,同时,DNS里记录的信息要和这里加密的头信息保持一致,比如在DKIM_HEADER_TEMPLATE里记录:

s=s1; d=mail.banping.com

否则邮件接收方在验证DNS信息的时候不匹配,认证会无法通过。还有就是发件人无法显示中文,会乱码,邮件标题和内容里的中文乱码的问题,可以通过设置utf-8解决。

update 20120330 :如果你的用于发送邮箱配置了腾讯的企业邮箱,那么发送到QQ邮箱的邮件列表会显示Amazon的发件地址,同时会提示此邮件地址未验证之类的信息,解决的办法是不要使用腾讯的企业邮箱。

TechClub第六次技术沙龙小记

上周日,TechClub第六次技术沙龙在@爱特咖啡举行,这次报名的人很多,最后到场的大概有40多位朋友,大家度过了一个愉快的下午,一场技术的盛宴。

这次活动的技术话题是国内知名,国际上也有很多用户的两个开源项目,手机游戏引擎cocos2d-x和高性能web app server,基于Nginx的openresty。两位讲师来自两个项目的研发团队或主导人员,绝对是重量级的分享。

张彬(来自cocos2d-x,捕鱼达人研发团队)分享的第一个话题:

 

技术大牛,openresty项目发起人 @agentzh 带来的第二个话题:

 

春哥开发的很多Nginx模块有很多国际知名的互联网公司在用,今天听了现场分享,确实太给力了,效率没的说。

希望以后能邀请到更多这样的朋友来和大家分享技术,学然后知不足,交流才能进步。

更多分享资料请移步TechClub官网:http://www.tech-club.org/?p=247

过年

正在过年。

外面下着雨,冷雨。

撑一纸雨伞,回到空旷的房子里。

空旷而幽暗,听见金鱼的呼吸。

感悟,想要说些什么,却不知从何说起。

电梯里,ONLY SMS.

不想看春晚了,没有坚持的心情和欲望。

RT上,微博上,流淌着节日的时光。

翻了翻前几天的日子,模糊而碎片。

时间溜走了。

就在那弹指一挥。

翻看david的博客,想象他怎样的被青春打湿双眼。

想象那无法回到的过去,之中的人和事。

其实,一个人经历的,正是大多数人经历的,

所以,世界上 ,才会有共鸣。

所以,诗人才会钟爱某一种水果。(亦或植物?)

所以,81才会面对年复一年的问题。

所以,张导和八达才能把简单的情节演绎的刻骨,

因为,那就是他,或他们自己。

桌上的mac,竟然没有去折腾它的欲望,

还一直没打开。

鞭炮,让我想起黄洋界上的诗句。

有时候,生活应是如此的简单,平和,感恩,幸福。

有时候,情绪却是魔鬼。

这正是鲜活动人生啊,

无需去刻意的改变,和逃避。

在纯粹的时间里看书,

竟然获得意外的充实,

我,其实很容易满足。

——————我是华丽的分割线———————-

一直没有心情和时间来想和看。

我常说,不仅要埋头做事,更要抬头看路。

方向很重要,

得过且过的生活态度,

会麻木一个人的心灵,

所以,每个人要有目标,要去学习。

为了现在,为了将来。

为了自己,为了团队。

那天,和古怪精灵的幸子吃全家福,

在街上找奖状而不是荣誉证书,

在花店里讨价还价,

在忙碌。

其实一直心怀感恩,

在这样的一个团队里很开心,

那一起走过的岁月,

和小黑屋里的每一个人。

无怨无悔,但是要努力。

机会,压力,责任。

——————我是华丽的分割线———————-

想去鼓浪屿走走,

一直有很多值得发现的痕迹,

而以后,或许上岛的机会就不多了,

不想遗憾,

亦或,

想度过这闲暇时间。

想过不一样的生活,

自由和梦想。

现在,

在过年,

这一刻,烟花绚烂。

从2011到2012

今天是2012年的第一天,元旦佳节,过去的2011虽然已经成为历史,但是依然是值得铭记的时光。

昨天是2011年的最后一天,遭遇了诸多的不顺利。

在下班的路上,车很拥堵,虽然我出来的已经很晚了,可是还是被这个车堵在了路上:

后来终于到了天虹,在地下二层停车场找了很久也没有找到停车位,爆满了,中间还接了Jimmy一个电话。最后终于在一个角落把车停了下来,耗时N久。

在天虹买了些东西,结果小票不小心丢掉了,本来凭小票是可以免费停车的,没办法只能乖乖的交停车费出来。

在出口的路上一样拥堵,各种车各种抢道,凭借极大的耐心好不容易才杀出重围。

回家煮面吃,想开一瓶酒,结果不小心酒瓶打落在地,摔得粉碎,满屋酒气。

希望,这些小小的不顺利就停留在2011,不再追随。

徐志摩说:

轻轻的,我走了,正如我轻轻的来,

我轻轻的挥手,作别西天的云彩。

没有人能阻挡时光匆匆的脚步,我们能做的,唯有珍惜和感恩。

因为那曾经虚度的青春,永远永远不再回来。

2012会更好,因为路,就在脚下,需要留下我们的足迹。

MySQL主从复制出错案例一则

有时候为了方面的导入数据,可以使用MyISAM存储引擎的表,直接把数据文件Copy一份放到对应的目录下,这样MySQL就能直接识别到,但是在主从复制的环境里这样做是有问题的,因为在从库上并没有这个表,从而导致后续的一些操作失败,比如在主库上执行导入数据的SQL语句,则在从库会报错如下:

mysql> show slave statusG
Slave_IO_Running: Yes
Slave_SQL_Running: No
Last_Errno: 1146
Last_Error: Error ‘Table ‘banpingdb.blog_score’ doesn’t exist’ on query. Default database: ‘banpingdb’. Query: ‘replace INTO blog_score_result(id,score,avg)
SELECT b.id, min(s.comment), min(s.price) FROM blog_score s,a_blog b where s.name=b.biz_name
group by b.id’

同样的信息通过日志也一样会看到:

111215 19:17:54 [ERROR] Slave SQL: Error ‘Table ‘banpingdb.blog_score’ doesn’t exist’ on query. Default database: ‘banpingdb’. Query: ‘replace INTO blog_score_result(id,score,avg)
SELECT b.id, min(s.comment), min(s.price) FROM blog_score s,a_blog b where s.name=b.biz_name
group by b.id’, Error_code: 1146
111215 19:17:54 [Warning] Slave: Table ‘banpingdb.blog_score’ doesn’t exist Error_code: 1146
111215 19:17:54 [ERROR] Error running query, slave SQL thread aborted. Fix the problem, and restart the slave SQL thread with “SLAVE START”. We stopped at log ’1-bin.000001′ position 130482476

这种错误处理也很简单,可以直接跳过,当然要评估可能产生的影响:

mysql> slave stop;
Query OK, 0 rows affected (0.22 sec)

mysql> SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1;
Query OK, 0 rows affected (0.00 sec)

mysql> slave start;
Query OK, 0 rows affected (0.00 sec)

然后blog_score_result这个表的数据肯定不准确了,可以重新从主库导入数据,视应用的繁忙程度,要保证数据的一致性,先在主库上lock这个表,不让其他用户更新:

mysql> lock tables blog_score_result read;
Query OK, 0 rows affected (0.00 sec)

然后导出数据:

[root@banping 3306]# bin/mysqldump –default-character-set=utf8 banpingdb blog_score_result -u root -p>/tmp/blog_score_result.sql;

去从库导入数据:

[root@banping 3306]# bin/mysql –default-character-set=utf8 banpingdb -u root -p</tmp/blog_score_result.sql;
Query OK, 0 rows affected (0.00 sec)

到主库解锁这个表:

mysql> unlock tables;
Query OK, 0 rows affected (0.00 sec)

这样就完成了数据一致性的操作。主从复制的同步也正常了。这种事情的处理要结合实际应用情况,不可照搬就是了。

配置Postfix邮件系统的访问权限

Postfix邮件系统的配置主要通过main.cf文件,路径在/etc/postfix下。如果要允许其他服务器使用Postfix的服务,需要重点关注inet_interfaces和mynetworks这两个参数。

# The inet_interfaces parameter specifies the network interface
# addresses that this mail system receives mail on. By default,
# the software claims all active interfaces on the machine. The
# parameter also controls delivery of mail to user@[ip.address].
#
# See also the proxy_interfaces parameter, for network addresses that
# are forwarded to us via a proxy or network address translator.
#
# Note: you need to stop/start Postfix when this parameter changes.
#
inet_interfaces = all

要注意的是,修改这个参数必须要停止再启动Postfix,单纯的restart是不生效的。

# You can also specify the absolute pathname of a pattern file instead
# of listing the patterns here. Specify type:table for table-based lookups
# (the value on the table right-hand side is not used).
#
mynetworks = 11.12.13.14,127.0.0.0/8

这个参数指定了要使用Postfix的IP地址,如果不设定正确,会在maillog里看到类似如下的提示信息:

Dec 1 11:16:21 mail postfix/smtpd[21197]:warning: 11.12.13.14: address not listed for hostname banping.com
Dec 1 11:16:21 mail postfix/smtpd[21197]: connect from unknown[11.12.13.14]
Dec 1 11:16:21 mail postfix/smtpd[21197]: NOQUEUE: reject: RCPT from unknown[11.12.13.14]: 554 5.7.1: Relay access denied; from= to= proto=ESMTP helo=<banping.com>

自己搭建邮件系统还是比较折腾的,使用Amazon ses是比较便捷的做法。

Xtrabackup 1.6.3安装及恢复数据

Xtrabackup是备份MySQL的很好的工具,目前最新的版本是1.6.3,和之前出过的1.6版本改进了不少,官方Percona目前对1.6.3的文档也改进了很多。安装包不再包含MySQL源码文件了,要根据需要从Percona在Amazon aws的服务器上下载,当然也可以自己下载需要的文件。

安装Xtrabackup,可以通过源码安装,也可以拿二进制程序过来直接使用,以下是源码安装的过程:

[root@data banping]# wget http://www.percona.com/redir/downloads/XtraBackup/XtraBackup-1.6.3/source/xtrabackup-1.6.3.tar.gz
[root@data banping]# tar zxf xtrabackup-1.6.3.tar.gz
[root@data banping]# cd xtrabackup-1.6.3
[root@data xtrabackup-1.6.3]# AUTO_DOWNLOAD=”yes” ./utils/build.sh 5.5

自动下载的是libtar-1.2.11.tar.gz和mysql源码文件,mysql的版本根据给定的参数识别,可选的有以下版本:

Value Alias Server
innodb51_builtin 5.1 build against built-in InnoDB in MySQL 5.1
innodb51 plugin build agsinst InnoDB plugin in MySQL 5.1
innodb55 5.5 build against InnoDB in MySQL 5.5
xtradb51 xtradb build against Percona Server with XtraDB 5.1
xtradb55 xtradb55 build against Percona Server with XtraDB 5.5

默认libtar并不会安装,如果需要使用stream功能,需要手动安装这个程序。安装完成后,会生成一个xtrabackup_innodb55文件,可以用它恢复innodb数据,文件的路径如下:

Target Location
innodb51_builtin mysql-5.1/storage/innobase/xtrabackup
innodb51 mysql-5.1/storage/innodb_plugin/xtrabackup
innodb55 mysql-5.5/storage/innobase/xtrabackup
xtradb51 Percona-Server-5.1/storage/innodb_plugin/xtrabackup
xtradb55 Percona-Server-5.5/storage/innobase/xtrabackup

恢复的方法如下:

[root@data recover]# /banping/xtrabackup_innodb55 –prepare –target-dir=/banping/recover/

prepare就是recover的过程,也就是通过前滚和回滚使数据一致,target-dir就是备份出来的文件路径。这一步的操作和MySQL Server是没有任何关系的。官方还建议执行两次prepare以便生成新的redo文件,个人认为是没什么必要的。

关于1.6版本的安装及备份和Xtrabackup的原理,请参见我以前的文章:

http://www.banping.com/2011/04/14/xtrabackup-mysql55/

http://www.banping.com/2011/05/24/xtrabackup-stream-mysql/

http://www.banping.com/2011/07/01/xtrabackup-process-backgroud/

 

TechClub活动的一次分享

10月份的TechClub活动上,我分享了一个话题,时间过去很久了,现在抽空放出来和大家分享。

TechClub的活动正在吸引着越来越多的朋友参与,这是一个公益活动,希望能有更多的朋友能到这个平台上分享自己的经验。

再奉上一张活动现场照片: