缘起:
tokyotyrant自有的master<->master, master->slave 模式已经不能满足业务的需要,现在期望可以随意复制,选择性复制。
办法:
1. 我们可以直接分析ulog来实现
2. 我们可以参考tokyotyrant的复制协议,通过socket来复制,或者使用C来实现,或者使用自己熟悉的语言实现
3. tokyotyrant提供了一个tcrmgr的工具,其中的repl子命令可以帮助我们通过socket复制数据,我们就可以使用自己熟悉的语言,将输出的信息解析后处理,同步到自己想同步到的地方去
PHP代码:
这里仅仅实现了两个命令的解析。
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 31 32 33 34 35 36 |
<?php define("PUT", "10"); define("OUT", "20"); while(!feof(STDIN)) { $str = trim(fgets(STDIN)); if (!$str) continue; $arr = explode("\t", $str); parse_record($arr[3]); } exit; function parse_record($str) { $str = str_replace(" ", "", $str); if (strlen($str) < 4) return false; $magic = substr($str, 0, 2); $cmd = substr($str, 2, 2); if ($magic != "C8") return false; switch($cmd) { case OUT: $ksiz = hexdec(substr($str, 4, 8)) * 2; $key = pack("H*", substr($str, 12, $ksiz)); echo "out\t", $key ,"\n"; break; case PUT: $ksiz = hexdec(substr($str, 4, 8)) * 2; $key = pack("H*", substr($str, 20, $ksiz)); $vsiz = hexdec(substr($str, $ksiz + 18, 8)) * 2; $val = pack("H*", substr($str, $ksiz + 20, $vsiz)); echo "put\t", $key , "\t", $val, "\n"; break; default: } return true; } |
使用方法:
tcrmgr repl -port 4242 -ts 1345999492000000 -sid 1234 -ph 10.71.6.28|php repl.php
记录格式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
struct record{ int magic; // 0xc8 int cmd; // put: 0x10; delete 0x20; ... ... } struct put_record{ int magic; // 0x80 int cmd; // 0x10 int32 ksiz; char *key; int32 vsiz; char *val; } struct delete_record{ int magic; // 0x80 int cmd; // 0x20 int32 ksiz; char *key; } |