redis (Remote Dictionary Server)是一個開源(BSD許可)的,內存中的數據結構存儲系統,它可以用作數據庫、緩存和消息中間件。它支持存儲的value類型相對更多,包括string(字符串)、list(鏈表)、set(集合)、zset(sorted set --有序集合)和hash(哈希類型)。Redis支持主從同步。數據可以從主服務器向任意數量的從服務器上同步,從服務器可以是關聯其他從服務器的主服務器。這使得Redis可執行單層樹複製。
MySQL和Redis,自身都帶有數據同步的機制,像比較常用的MySQL的Master/Slave模式,就是由Slave端分析Master的binlog來實現的,這樣的數據複製其實還是一個異步過程,只不過當服務器都在同一內網時,異步的延遲幾乎可以忽略。那麼理論上我們也可以用同樣方式,分析MySQL的binlog文件並將數據插入Redis。但是這需要對binlog文件以及MySQL有非常深入的理解,同時由於binlog存在Statement/Row/Mixedlevel多種形式,分析binlog實現同步的工作量是非常大的。因此這裏選擇了一種開發成本更加低廉的方式,借用已經比較成熟的MySQL UDF,將MySQL數據首先放入Gearman中,然後通過一個自己編寫的PHP Gearman Worker,將數據同步到Redis。比分析binlog的方式增加了不少流程,但是實現成本更低,更容易操作。
Gearman是一個支持分佈式的任務分發框架:
Gearman Job Server:Gearman核心程序,需要編譯安裝並以守護進程形式運行在後臺。
Gearman Client:可以理解爲任務的請求者。
Gearman Worker:任務的真正執行者,一般需要自己編寫具體邏輯並通過守護進程方式運行,Gearman Worker接收到Gearman Client傳遞的任務內容後,會按順序處理.
大致流程:
mysql觸發器,就相當於Gearman的客戶端。修改表,插入表就相當於直接下發任務。然後通過lib_mysqludf_json UDF庫函數將關係數據映射爲JSON格式,然後在通過gearman-mysql-udf插件將任務加入到Gearman的任務隊列中,最後通過redis_worker.php,也就是Gearman的worker端來完成redis數據庫的更新。
使用lib_mysqludf_json的原因是因爲Gearman只接受字符串作爲入口參數,可以通過lib_mysqludf_json將MySQL中的數據編碼爲JSON字符串.
lib_mysqludf_json UDF庫函數將關係數據映射爲JSON格式。通常,數據庫中的數據映射爲JSON格式,是通過程序來轉換的。
1. server2:
配置redis:
yum install -y mysql-server
/etc/init.d/mysqld start
netstat -antlpe ##mysql端口3306已開
tar zxf redis-3.0.2.tar.gz
cd redis-3.0.2
yum install -y gcc
make
make install
cd /root/redis-3.0.2/utils
./install_server.sh ##安裝服務器啓動程序
/etc/init.d/redis_6379 start
redis-cli monitor ##監控數據,okshi表示監控正常
redis-cli ##臨時設定redis的一些數據
redis作爲mysql緩存服務器:
cd /root
yum install nginx-1.8.0-1.el6.ngx.x86_64.rpm php-5.3.3-38.el6.x86_64.rpm
php-cli-5.3.3-38.el6.x86_64.rpm php-common-5.3.3-38.el6.x86_64.rpm php-devel-5.3.3-38.el6.x86_64.rpm php-fpm-5.3.3-38.el6.x86_64.rpm
php-gd-5.3.3-38.el6.x86_64.rpm php-mbstring-5.3.3-38.el6.x86_64.rpm
php-mysql-5.3.3-38.el6.x86_64.rpm php-pdo-5.3.3-38.el6.x86_64.rpm
php -m ##看到支持的軟件
vim /etc/php.ini
date.timezone = Asia/Shanghai
cat /etc/passwd
vim /etc/php-fpm.d/www.conf
user = nginx group = nginx
/etc/init.d/php-fpm restart
配置nginx:
vim /etc/nginx/conf.d/default.conf
location / { root /usr/share/nginx/html; index index.html index.htm index.php; } location ~ \.php$ { root html; fastcgi_pass 127.0.0.1:9000; ##fastcgi通信 fastcgi_index index.php; ##fastcgi主文件 fastcgi_param SCRIPT_FILENAME /usr/share/nginx/html$fastcgi_script_name; include fastcgi_params; }
cd /usr/share/nginx/html/
vim index.php
<?php phpinfo() ?>
/etc/init.d/nginx start
網頁訪問http://172.25.85.2
nginx上運行php:
yum install -y unzip
unzip phpredis-master.zip
cd phpredis-master
phpize
./configure
make
make install
cd /usr/lib64/php/modules/
ls
cd /etc/php.d
cp mysql.ini redis.ini
vim redis.ini
將內容修改爲以下:
extension=redis.so
/etc/init.d/php-fpm reload
php -m | grep redis
mysql
mysql> show databases; ##查看有無test數據庫,沒有則創建一個。
mysql> quit
cd /root/redis
mysql < test.sql
cat test.sql
use test; CREATE TABLE `test` (`id` int(7) NOT NULL AUTO_INCREMENT, `name` char(8) DEFAULT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8; INSERT INTO `test` VALUES (1,'test1'),(2,'test2'),(3,'test3'),(4,'test4') ,(5,'test5'),(6,'test6'),(7,'test7'),(8,'test8'),(9,'test9'); #DELIMITER $$ #CREATE TRIGGER datatoredis AFTER UPDATE ON test FOR EACH ROW BEGINmysql < test.sql SET @RECV=gman_do_background('syncToRedis', json_object(NEW.id as `id`, NEW.name as `name`)); END$$ #DELIMITER ;
mysql
mysql> use test;
mysql> select * from test;
mysql> grant all on *.* to redis@localhost identified by 'westos';
mysql> quit
mysql -uredis -pwestos
mysql> use test;
mysql> select * from test;
mysql> quit
cp /root/test.php /usr/share/nginx/html/
cd /usr/share/nginx/html/
rm -rf index.php
mv test.php index.php
檢測:
網頁訪問http://172.25.85.2 ##已經完成redis對mysql的緩存
redis-cli
127.0.0.1:6379> get 1
"test1"
127.0.0.1:6379> get 2
"test2"
127.0.0.1:6379> quit
mysql
mysql> use test;
mysql> update test set name='westos' where id=1;
mysql> quit
網頁訪問http://172.25.85.2 ##更新了mysql中的數據,但是redis中的數據不會自動更新
redis-cli 127.0.0.1:6379> get 1 "test1" redis-cli 127.0.0.1:6379> del 1 網頁訪問http://172.25.85.2 redis-cli 127.0.0.1:6379> set 1 westos 網頁訪問http://172.25.85。2
Gearman是一個支持分佈式的任務分發框架:
Gearman Job Server:Gearman核心程序,需要編譯安裝並以守護進程形式運行在後臺。
Gearman Client:可以理解爲任務的請求者。
Gearman Worker:任務的真正執行者,一般需要自己編寫具體邏輯並通過守護進程方式運行,Gearman Worker接收到Gearman Client傳遞的任務內容後,會按順序處理
大致流程:
下面要編寫的mysql觸發器,就相當於Gearman的客戶端。修改表,插入表就相當於直接下發任務。然後通過lib_mysqludf_json UDF庫函數將關係數據映射爲JSON格式,然後在通過gearman-mysql-udf插件將任務加入到Gearman的任務隊列中,最後通過redis_worker.php,也就是Gearman的worker端來完成redis數據庫的更新。
2.配置gearman自動更新redis中的數據:
cd /root/redis
yum install -y gearmand-1.1.8-2.el6.x86_64.rpm libgearman-1.1.8-2.el6.x86_64.rpm
/etc/init.d/gearmand start
netstat -antlpe
tar zxf gearman-1.1.2.tgz
cd gearman-1.1.2
phpize
./configure
cd ..
yum install -y libgearman-devel-1.1.8-2.el6.x86_64.rpm
libevent-devel-1.4.13-4.el6.x86_64.rpm
libevent-doc-1.4.13-4.el6.noarch.rpm
libevent-headers-1.4.13-4.el6.noarch.rpm
cd gearman-1.1.2
./configure
make
make install
cd /etc/php.d
cp redis.ini gearman.ini
vim gearman.ini
將內容修改爲以下:
extension=gearman.so
/etc/init.d/php-fpm reload
php -m |grep gearman
yum install -y mysql-devel
cd /root/redis
lib_mysqludf_json UDF庫函數將關係數據映射爲JSON格式。通常,數據庫中的數據映射爲JSON格式,是通過程序來轉換的。
unzip lib_mysqludf_json-master.zip
cd lib_mysqludf_json-master
gcc $(mysql_config --cflags) -shared -fPIC -o lib_mysqludf_json.so lib_mysqludf_json.c
ls
mysql
mysql> show global variables like 'plugin_dir';
mysql> quit
cd /root/lib_mysqludf_json-master
cp lib_mysqludf_json.so /usr/lib64/mysql/plugin
#註冊UDF函數
mysql
mysql> create function json_object returns string soname 'lib_mysqludf_json.so';
mysql> select * from mysql.func;
mysql> quit
#安裝gearman-mysql-udf
這個插件是用來管理調用 Gearman 的分佈式的隊列。
cd /root/redis
tar zxf gearman-mysql-udf-0.6.tar.gz
cd gearman-mysql-udf-0.6
yum install -y gcc-c++
./configure --libdir=/usr/lib64/mysql/plugin/
make
make install
cd /usr/lib64/mysql/plugin/
mysql -p
#註冊UDF函數
mysql> create function gman_do_background returns string soname 'libgearman_mysql_udf.so';
mysql> create function gman_servers_set returns string soname 'libgearman_mysql_udf.so';
#查看函數
mysql> select * from mysql.func;
mysql> quit
netstat -antlpe
#指定gearman的服務信息
mysql
mysql> select gman_servers_set('127.0.0.1:4730');
mysql> quit
#編寫mysql觸發器(根據實際情況編寫)
cd /root/redis
vim test.sql
將觸發器的註釋取消,在建表和插入數據語句前加上註釋
DELIMITER $$ CREATE TRIGGER datatoredis AFTER UPDATE ON test FOR EACH ROW BEGIN SET @RECV=gman_do_background('syncToRedis', json_object(NEW.id as `id`, NEW.name as `name`)); END$$ DELIMITER ;
mysql < test.sql
mysql
mysql> show triggers from test;
mysql> quit
cp worker.php /usr/local/bin/
cd /usr/local/bin/
vim worker.php
nohup php worker.php &
ps ax
mysql
mysql> use test;
mysql> update test set name='redhat' where id=1;
mysql> quit
網頁訪問http://172.25.19.1(刷新) ##更新 (待驗證)
redis-cli
127.0.0.1:6379> get 1
"redhat"
3.redis的主從複製
如果設置了一個slave,不管是在第一次鏈接還是重新鏈接master的時候,slave會發送一個同步命令 然後master開始後臺保存,收集所有對修改數據的命令。當後臺保存完成,master會將這個數據文件傳送到slave,然後保存在磁盤,加載到內存中;master接着發送收集到的所有的修改數據的命令,這好比一個流命令,是redis協議本身來實現的。
在server3和server4上:
vim /etc/redis/6379.conf
slaveof 172.25.85.2 6379
/etc/init.d/redis_6379 restart
server2:
vim /root/redis-3.0.2/sentinel.conf ##配置sentinel
sentinel monitor mymaster 172.25.85.2 6379 2
##Sentinel 去監視一個名爲 mymaster 的主服務器, 這個主服務器的 IP 地址爲 127.0.0.1 , 端口號爲 6379 , 而將這個主服務器判斷爲失效至少需要 2 個 Sentinel 同意 (只要同意 Sentinel 的數量不達標,自動故障遷移就不會執行)。
sentinel down-after-milliseconds mymaster 10000
##Sentinel 認爲服務器已經斷線所需的毫秒數。
sentinel failover-timeout mymaster 60000
grep -v ^# sentinel.conf >/etc/sentinel.conf
redis-sentinel /etc/sentinel.conf
tu
scp /etc/sentinel.conf [email protected]:/etc/
scp /etc/sentinel.conf [email protected]:/etc/
redis-cli -h 172.25.45.7 -p 26379 info
tu
server4:
vim /etc/sentinel.conf
port 26379
dir "/tmp"
.
sentinel monitor mymaster 172.25. 6379 2
sentinel down-after-milliseconds mymaster 10000
sentinel failover-timeout mymaster 60000
sentinel parallel-syncs mymaster 1 ##選項指定了在執行故障轉移時, 最多可以有多少個從服務器同時對新的主服務器進行同步, 這個數字越小, 完成故障轉移所需的時間就越長。
scp /etc/sentinel.conf [email protected]:/etc/
然後再server7查看:redis-cli -h 172.25.85.2 -p 26379 info
tu