之所以使用python,是因为python多线程非常简单。
之所以使用shell,是因为写了个服务,可以方便的重启python写的那个脚本。
总体思路:利用redis的发布订阅,php作为生产者,python作为消息费,来实现多台redis-master数据同步。中间也用了redis的list。
当然多台redis-master可以做一个redis集群,然后再两两同步。这里不讨论这么情况的实现。
1、PHP代码(php作为消息生产者,也就是客户端)
$redis = new Redis(); $redis->connect('127.0.0.0', 6379); $redis->set('test', '123');//设置一个key/value $count = $redis->lpush('rsync_list', 'test'); // 把key放到rsync_list这个队列里,做为同步使用 $redis->publish('rsync_list', $count);//发布一个消息,channel为rsync_list,用于python代码订阅的channel
2、PYTHON代码(python做为消息接收者,也就是服务端)
/home/www/py/muti_thread_redis.py
#!/usr/bin/env python #coding=utf-8 import threading import redis MAIN_HOST = '127.0.0.1' MAIN_PORT = 6379 MAIN_PASS = '' RSYNCLIST = 'rsync_list' def infinite(): global rc ps = rc.pubsub() ps.subscribe('rsync_list') threads = [] while True: data = ps.parse_response() if data[2] > 0: #第一台 t1 = threading.Thread(target=write1,args=(data[2],)) t1.start() threads.append(t1) #第二台 t2 = threading.Thread(target=write2,args=(data[2],)) t2.start() threads.append(t2) for t in threads: t.join() #子进程执行完之后,清空list def write1(args): global rc global RSYNCLIST redis_one = redis.Redis(host='127.0.0.1',port=6380,password='') for i in rc.lrange(RSYNCLIST, 0, -1): redis_one.set(i, rc.get(i)) def write2(args): global rc global RSYNCLIST redis_two = redis.Redis(host='127.0.0.1',port=6381,password='') for i in rc.lrange(RSYNCLIST, 0, -1): redis_two.set(i, rc.get(i)) if __name__ == '__main__': rc =redis.Redis(host=MAIN_HOST,port=MAIN_PORT,password=MAIN_PASS) infinite()
注意:这里python和python的redis扩展的安装,就不在这里赘述了。baidu里很多
3、shell(做为一个服务用来启动python的服务端脚本)
cd /etc/init.d
新建一个脚本:vim rsync-redis
#!/bin/bash #chkconfig:2345 55 25 //运行级别、启动优先级、关闭优先级 #processname:rsync-redis //进程名 #description:source rsync-redis server daemon //服务描述 prog=/usr/bin/python lock=/home/www/py/rsync_redis.pid start(){ echo "[正在启动服务...]" $prog /home/www/py/muti_thread_redis.py & echo "[OK]" touch $lock } stop(){ echo "[正在停止服务...]" pkill -f muti_thread_redis.py rm -f $lock echo "[OK]" } status(){ if [ -e $lock ];then echo "$0 服务正在运行" else echo "$0 服务已经停止" fi } restart(){ stop start } case "$1" in "start") start ;; "stop") stop ;; "status") status ;; "restart") restart ;; *) echo "用法:$0 start|stop|status|restart" ;; esac
然后就可以用/etc/init.d/rsync-redis start/stop/restart/status来操作了。