$劣头->翔(); http://littlexiang.me/ zh-CN Ubuntu系伪Linux爱好者, 半个程序猿+半个运维+半个架构, 神马都懂一点 Thu, 31 Jan 2013 13:47:35 +0800 Thu, 31 Jan 2013 13:47:35 +0800 Mint 14 x86_64安装wine rtx 2011 http://littlexiang.me/linux/install-wine-rtx-on-linux-x86_84.html http://littlexiang.me/linux/install-wine-rtx-on-linux-x86_84.html Thu, 31 Jan 2013 13:47:35 +0800 劣头翔 刚重装了系统,换到了Mint 14。 之前一直是装虚拟机xp跑rtx的,可是很不方便,内存也不够用,就考虑装wine rtx。
sudo add-apt-repository ppa:ubuntu-wine/ppa
sudo apt-get update
sudo apt-get install wine winetricks
winetricks msxml3 gdiplus riched20 riched30 vcrun6 vcrun2005sp1 vcrun6sp6 vb6run
wine rtxclient2011formal.exe

winetricks过程中可能会让手动去下载包, 照做即可。可能会有一些i386 lib找不到的报错,无视。
安装rtx最后会报一个注册错误,直接跳过。
第一次打开的时候 登录成功, 但是紧接着就卡死了。。。。。。
然后我安装了ia32-libs, 并把环境设置为win7, 然后就神奇地搞定了。

sudo apt-get ia32-libs
winetricks -q win7

无图无真相

会有方块,别人看你的字是横着的,稍微调整一下设置



理论上也同样适用于Ubuntu 12.10

]]>
0 http://littlexiang.me/linux/install-wine-rtx-on-linux-x86_84.html#comments http://littlexiang.me/feed/default/start.html
shell拾遗 http://littlexiang.me/linux/8.html http://littlexiang.me/linux/8.html Wed, 16 Jan 2013 16:56:12 +0800 劣头翔 最近在做分析统计日志的活,又把各种linux下工具拾起来了. 这个做个备忘. (本文持续更新中...)


多进程并行执行的时候将结果重定向到不同文件


ls /home/ | xargs -n1 -P 10 sh -c "echo %0 >> /tmp/\$$.tmp;"

命令标准输出直接赋值到变量


YESTERDAY=$(date -I -d'1 day ago')
echo "---------------------------------"
echo $YESTERDAY
]]>
0 http://littlexiang.me/linux/8.html#comments http://littlexiang.me/feed/default/start.html
基于Redis的Feed推送系统(四) - 零零碎碎 http://littlexiang.me/architecture/7.html http://littlexiang.me/architecture/7.html Sun, 06 Jan 2013 17:41:21 +0800 劣头翔 扩展性/性能/高可用

gearman大概每秒可以接收4k个任务, 单台的能力都是足够了,配置成LVS backup-backup模式切换. 任务通过gearman的扩展写入mysql持久化, 后端的mysql也是Master-Master+LVS切换, 杜绝单点.

aggregator的性能可以通过单组多slave和多组分布+2次mapreduce扩展

distributor的性能可以通过增加worker机和inbox的redis实例提高. 

个人feed的redis需要持久化, 每个节点都有3台: 主->备->持久, 通过LVS切换, 主和备都是纯内存, 持久机不参与工作,只负责写aof.

inbox缓存的redis全部都是纯内存, 可以有多台互相作为备机.


worker管理/健康检查


一开始是用pcntl接管了kill信号, 保证不会在任务进行中被kill掉, 不过strace发现有很多system call比较浪费, 于是改成从数据库读信号.worker做完一个任务后去数据库更新状态, 然后检查kill信号并记log.

start/stop/restart都统一由Manager脚本控制, 除非挂了, 正常情况下不许直接kill. Manager还带有watch功能, 每分钟检查一次所有进程的状态.

Monitor脚本循环跑一个空任务, 做一个sleep一会新增一个, 检查gearman server的状态.


吐槽


尼马gearman 1.1.4是坑爹的啊!mysql断了不会重连, 编译drizzle怎么也搞不上, 换0.41啥事都没有啊!

尼马php的gearman client是坑爹的啊! addServers两台有一台挂了直接就连不上啊!说好的自动failover呢!

马php的redis扩展是坑爹的啊!没有连接池吃CPU又高, 这是闹那样啊!

虽然php5.3换5.4性能有很大提高, 不过还是准备改写成python的, 毕竟后台worker嘛...

]]>
4 http://littlexiang.me/architecture/7.html#comments http://littlexiang.me/feed/default/start.html
基于Redis的Feed推送系统(三) - 分发器 http://littlexiang.me/architecture/6.html http://littlexiang.me/architecture/6.html Sun, 06 Jan 2013 17:01:12 +0800 劣头翔 分发器负责向所有在线的用户推送feed, 即前文中的Distributor.

用户产生一条新feed, 先同步插入自己的inbox, 然后交给Distributor分发给所有粉丝.

这里worker有2层, worker1负责接收任务, 按照每3000个粉丝一组分拆成很多子任务, 交给下一级worker2处理. worker2并行处理完成后汇报给worker1, 同时做一些计时和延误告警的工作. 

worker2负责具体的分发流程, 获取粉丝id->判定online->推送并未读数++. 为了追求速度, online是一次性批量获取的, 这里还碰到过一个坑, 参见 http://littlexiang.me/php/3.html .

同时worker2也有大小两个池, 初步设定threshold是100w, 超过100w粉丝的任务会交给large pool处理, 避免某些大佬发了照片来不及处理导致任务积压, 影响了大部分普通用户的分发.

关于性能, 模拟了100w粉丝全体offline和online的情况. 100个worker+2个redis在普通pc机上的分别是1~2s和10~11s.这里扯一个别的问题, 之前测试1个redis的时候, 分发速度是6~7w/s, 分布到2个redis之后居然还是6~7w/s, 最后发现是计算分布写的太罗嗦了, 后来把floor(crc32(id) % 360 / (360 / N))改成crc32(id) & (N-1), 达到了10w+/s, 缺点就是shard数量只能是2^n. 每次扩容必须翻倍, 不过不一定得加物理机, 直接多开一组redis实例就可以了, 因为是全缓存, 完全不用aof和rdb, 一台物理机上开个4个总是可以的.

关于inbox的分布和扩容, 直接添加配置就可以了. 因为online标志和inbox在一起, 所以不需要人工干预迁移, 失效的部分会在下一次用户操作时自动rebuild.

]]>
1 http://littlexiang.me/architecture/6.html#comments http://littlexiang.me/feed/default/start.html
基于Redis的Feed推送系统(二) - 动态聚合器 http://littlexiang.me/architecture/5.html http://littlexiang.me/architecture/5.html Sun, 06 Jan 2013 16:04:39 +0800 劣头翔 动态聚合的部分全部基于redis的sorted set, 采用mapreduce计算. 这就是前文中的Aggregator, 主要用于初始化和rebuild.

每个用户都有个人feed的队列, 用户得到的动态就是把所有关注者的feed队列内容聚合起来. 这里采用了mapreduce的计算方式, 先取出每个人的Top 20, 得到N个关注者的20xN条feed, 再进行排序得到最终的Top 20.

对性能做测试的时候, 按照关注上限3000人, 每人队列10000条做了模拟. 循环取3000次15s, 改用pipeline后0.5s, 最后变态地使用了邪恶的eval, 用lua脚本一次性在服务端做完再返回, 结果是0.2s.

    
do
    local ret = {}
    local t = loadstring('return ' .. ARGV[1])()
    for k,v in pairs(t) do
        local key = 'u:' .. v .. ':photos'
        local tmp = redis.call('ZREVRANGEBYSCORE', key, '(' .. ARGV[2], '-inf', 'WITHSCORES', 'LIMIT', '0', ARGV[3])
        table.insert(ret, tmp)
    end
    return ret
end

悲催的是redis的单线程的, 所以这个操作的并发性能很差. 根据redis文档描述 Time complexity: O(log(N)+M) with N being the number of elements in the sorted set and M the number of elements being returned. 耗时主要取决于每页的feed条数和关注的人数.

当然可以通过多个read slave来提高并发, 也可以将个人feed队列分布存储在多个redis中, 通过二次mapreduce并行计算.


需要翻页时提供上一页最后一条的score, 取小于score的20条, 才可以保证mapreduce翻页结果正确. 实际中简单地使用了精度到毫秒的时间戳作为score.



intval((microtime(true) - $epoch_ts) * 1000)

 



]]>
2 http://littlexiang.me/architecture/5.html#comments http://littlexiang.me/feed/default/start.html
基于Redis的Feed推送系统(一) - 整体设计思路 http://littlexiang.me/architecture/4.html http://littlexiang.me/architecture/4.html Sun, 06 Jan 2013 13:34:36 +0800 劣头翔 之前我们的Feed聚合是基于纯数据库IN查询, 条件多还要加上排序, 当数据超过1kw之后, 就开始有慢语句产生. 做了索引优化拆分成两条语句, 第一句只取id, 保证查询是index only, 然后再循环取单条feed. 尽管如此不久以后还是渐渐不行, 某些语句会扫描30w行, 大概在2s左右.于是开始构思如何模仿新浪微博的推送体系.找了很多blog都没有找到稍微是具体的实现细节,苦逼的只能自己半猜想半模拟了.

终于某天在梦中, 得到了粗略的思路.

再具体细化一些后的思路

分为推和拉两部分, 姑且称为Distributor和Aggregator.

用户初始化上线的时候, 第一次刷新动态列表, 此时inbox是空白的. 此时Aggregator负责动态聚合第一页数据返回, 同时online标志位标记为1, 当下触发Aggregator取20条x50页数据填充inbox, 同时Distributor开始对此用户推送新feed. 此情况只发生在 offline->online 状态切换的时候.

用户上线完成后只需要读取inbox的内容, Distributor负责持续向online用户推送.

online标志位缓存时间72小时, 同时inbox也保持一致的缓存ttl.

删除feed的情况由前端输出时过滤, 系统本身不处理. 一是此情况很少, 二是代价太高, 没有必要.

当发生关注/取消关注时, 同步将本人的online标志清除, 下一次用户刷新动态列表时会自动rebuild.


P.S. 该系统目前已经构建完成, 基于gearman+php+redis, 具体的实现细节之后再分篇阐述.

]]>
1 http://littlexiang.me/architecture/4.html#comments http://littlexiang.me/feed/default/start.html
php运算符的一个坑 http://littlexiang.me/php/3.html http://littlexiang.me/php/3.html Mon, 17 Dec 2012 12:38:45 +0800 劣头翔 以下运算会得到神码?


$final = false;
$v = true;
$final = $final or $v;

理所当然地以为会得到期望的结果, 但是结果永远是false. 理论上来说 or 的运算优先级比 = 高, 但是实际上php在这里有一个特例, 参见 http://www.laruence.com/2010/07/26/1668.html .


$a = 100 && $b = 100

理解为
($a = 100) && ($b = 100)

所以我的运算其实是
($final = $final) or $v;

坑爹那这是, 看来各种运算一定得加括号.

]]>
0 http://littlexiang.me/php/3.html#comments http://littlexiang.me/feed/default/start.html
蛋疼 http://littlexiang.me/default/start.html http://littlexiang.me/default/start.html Tue, 16 Oct 2012 11:42:12 +0800 劣头翔 新买的vps, 刚用了没一个礼拜就被人爆菊花了,万恶的弱口令啊......

]]>
4 http://littlexiang.me/default/start.html#comments http://littlexiang.me/feed/default/start.html