tokyo tyrant 在 php 上不能自动反序列化的问题

前一阵试用 tokyo tyrant 碰到一个麻烦,
在php上用memcache接口,取出数据的时候,不会自动反序列化。比如了一个 array(1,2,3,4,5),出来就是 ‘a:5:{i:0;i:1;i:1;i:2;i:2;i:3;i:3;i:4;i:4;i:5;}’ 了。

用 Wireshark 跟踪了一下,发现和标准memcached返回的数据里差一个字节。去看了下 memcached 协议,发现这个字节是个客户端的标记 flag 。存储的时候放置这个标志,取的时候照样返回。php 的 memcache 扩展应该就是用这个字节来标志是否是 php 的数据。如果匹配则反序列化。对比 tokyo tyrant 的源代码,发现它在存取的时候无视了这个标记位(其实还无视了一些其他东西,比如过期时间之类的,只用了 key 和 value 以及他们的长度),所以就有了这个结果。

之前考虑改 tokyo tyrant ,做了个补丁。不过正如 xdanger
所说,这个办法不好。之前测试得不仔细,后来试了几个不同的类型,果然是出了问题。于是又考虑再改 php
的客户端。让它不管什么类型存储的时候都去做序列号。似乎是解决了反序列号问题。这样修改版的客户端放的东西原版的能正常读取,但原版客户端一旦放了常规值就会出毛病。这一下同时改了客户端和服务端,另外,压缩的问题也还是没解决。看来这个问题还真的很难。

php 客户端补丁,修改 memcache.c
 http://syre.blogbus.com/files/12229540080.diff

 tokyo tyrant 补丁,修改 ttserver.c
http://syre.blogbus.com/files/12227686210.diff

 

将一个程序的输出接到两个程序的输入

unix的管道是个好东西,可以串起几个命令来实现强大的功能。不过有时候如果想要把一个程序的输出接到两个程序的输入,单靠 | 是不成了。要么先把程序的输出重定向到一个文件,不过这在输出量很大的时候不算是一个好办法。

下面是实现这种功能的一个方法:

mkfifo /tmp/fifo
prog2 < /tmp/fifo &
prog1 | tee /tmp/fifo | prog3

这就会把prog1 的标准输出同时给 prog2 和 prog3 的标准输入。

这里mkfifo是创建一个命名管道,这样可以有多个管道使,tee 则会把输出同时输出到一个文件和标准输出,实现了分岔。prog2 < /tmp/fifo & 这里要加个 &,不然管道里没数据 prog2就会阻塞。

这几行东西是从《Unix环境高级编程》上看来的。利用命名管道,还可以变出别的东西。

比如用diff比较两个命令的输出。

mkfifo /tmp/fifo1
mkfifo /tmp/fifo2
ls dir1 > /tmp/fifo1 &
ls dir2 > /tmp/fifo2 &
diff /tmp/fifo1 /tmp/fifo2

str_replace 容易被忽视的一点

str_replace 的前两个参数都可以是数组,当他们是数组时,会依次替换。比如 str_replace(array(‘a’, ‘1’), array(‘b’, ‘2’), ‘aaa111’); 的结果就是 bbb222。

但是这里 str_replace 的行为实际上并不是把 ‘a’ 映射为 ‘b’,把 ‘1’ 映射为 ‘2’,而是先做一轮替换,把 ‘a’ 替换为 ‘b’ ,再做一轮替换把 ‘1’ 替换为 ‘2’。在某些情况下,不了解这个情况,用str_replace 来做映射的时候就可能出错。

比如,想把 ‘a’ 映射为 ‘b’,把 ‘b’ 映射为 ‘c’,用str_replace(array(‘a’, ‘b’), array(‘b’, ‘c’), ‘abc’); 的结果不是 ‘bcc’ 而是 ‘ccc’。

要实现映射,得用另一个函数—— strtr。