mysql 5.1.17 redis_redis作为mysql的缓存服务器(读写分离)
一、redis簡介
Redis是一個key-value存儲系統(tǒng)。和Memcached類似,為了保證效率,數(shù)據(jù)都是緩存在內(nèi)存中。區(qū)別的是redis會周期性的把更新的數(shù)據(jù)寫入磁盤或者把修改操作寫入追加的記錄文件,并且在此基礎(chǔ)上實現(xiàn)了master-slave(主從)同步。在部分場合可以對關(guān)系數(shù)據(jù)庫起到很好的補充作用。它提供了Java,C/C++(hiredis),C#,PHP,JavaScript,Perl,Object-C,Python,Ruby等客戶端,使用很方便。
二、架構(gòu)圖
大致結(jié)構(gòu)就是讀寫分離,將mysql中的數(shù)據(jù)通過觸發(fā)器同步到redis中
三、安裝LNMP環(huán)境(這里為了省事,就是用yum來安裝)
1、修改yum源
1
2
3
4
5
6
7
8
9
10
11
12
13
[iyunv@redis ~]# vim /etc/yum.repos.d/epel.repo? ? #添加這個文件
[epel]
name=Extra Packages for Enterprise Linux 6 - $basearch
baseurl=http://download.fedoraproject.org/pub/epel/6/$basearch
failovermethod=priority
enabled=1
gpgcheck=0
[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/centos/6/$basearch/
gpgcheck=0
enabled=1
2、yum安裝
1
[iyunv@redis ~]# yum -y install nginx?php?php-fpm php-cli php-common php-gd php-mbstring php-mysql?php-pdo php-devel php-xmlrpc php-xml php-bcmath php-dba php-enchant mysql mysql-server
3、簡單配置一下nginx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[iyunv@redis ~]# vim /etc/nginx/nginx.conf
server {
listen? ?? ? 80;
#定義使用www.xx.com訪問
server_name??www.xx.com;
#設(shè)定本虛擬主機的訪問日志
access_log??/logs/www.xx.com.access.log??main;
#默認請求
location / {
root? ?/www/;? ?? ?#定義服務(wù)器的默認網(wǎng)站根目錄位置
index index.php index.html index.htm;? ?#定義首頁索引文件的名稱
}
location ~ \.php$ {
root /www/;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /www/$fastcgi_script_name;
include fastcgi_params;
}
}
4、啟動服務(wù)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[iyunv@redis ~]# sed -i 's/apache/nginx/g' /etc/php-fpm.d/www.conf
[iyunv@redis ~]# /etc/init.d/php-fpm start
正在啟動?php-fpm:? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ???[確定]
[iyunv@redis ~]# /etc/init.d/mysqld start
正在啟動?mysqld:? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?[確定]
[iyunv@redis ~]# mkdir /{logs,www}
[iyunv@redis ~]# chown -R nginx:nginx /{logs,www}
[iyunv@redis ~]# /etc/init.d/nginx start
正在啟動 nginx:? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? [確定]
[iyunv@redis www]# service iptables stop
iptables: Flushing firewall rules:? ?? ?? ?? ?? ?? ?? ?? ? [??OK??]
iptables: Setting chains to policy ACCEPT: filter? ?? ?? ? [??OK??]
iptables: Unloading modules:? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? [??OK??]
[iyunv@redis redis]# netstat -tnlp? ?? ?#查看監(jiān)聽
Active Internet connections (only?servers)
Proto Recv-Q Send-Q Local Address? ?? ?? ?? ?? ?Foreign Address? ?? ?? ?? ? State? ?? ? PID/Program name
tcp? ?? ???0? ?? ?0 0.0.0.0:80? ?? ?? ?? ?? ?? ?0.0.0.0:*? ?? ?? ?? ?? ?? ? LISTEN? ?? ?2101/nginx
tcp? ?? ???0? ?? ?0 127.0.0.1:9000? ?? ?? ?? ???0.0.0.0:*? ?? ?? ?? ?? ?? ? LISTEN? ?? ?7544/php-fpm
tcp? ?? ???0? ?? ?0 0.0.0.0:3306? ?? ?? ?? ?? ? 0.0.0.0:*? ?? ?? ?? ?? ?? ? LISTEN? ?? ?1871/mysqld
5、給mysql授權(quán)
1
2
3
4
[iyunv@redis ~]# mysql
mysql> grant all privileges on *.* to root@localhost identified by '123456';
mysql> flush privileges;
6、測試
1
2
3
4
[iyunv@redis ~]# vim /www/index.php
phpinfo();
?>
然后訪問頁面看到php的相關(guān)信息,基礎(chǔ)環(huán)境就算搭建完成了。
四、安裝redis
1、安裝redis
1
2
3
4
5
6
7
8
9
10
11
12
[iyunv@redis ~]# wget -c -t 0?http://download.redis.io/releases/redis-2.8.19.tar.gz
[iyunv@redis ~]# mkdir /usr/local/redis
[iyunv@redis ~]# tar xvf redis-2.8.19.tar.gz
#安裝很簡單、直接make就可以了
[iyunv@redis ~]# cd redis-2.8.19
[iyunv@redis redis-2.8.19]# make
#編譯完成后,將src中的可執(zhí)行文件拷貝到剛剛創(chuàng)建的目錄中
[iyunv@redis src]# cp redis-benchmark redis-check-aof redis-check-dump redis-cli redis-sentinel redis-server?/usr/local/redis/
[iyunv@redis redis-2.8.19]# cp redis.conf sentinel.conf /usr/local/redis/
Redis-benchmark? ?? ?壓力測試工具
Redis-check-aof? ?? ?檢查redis持久化命令文件的完整性
Redis-check-dump? ???檢查redis持久化數(shù)據(jù)文件的完整性
Redis-cli? ?? ?? ?? ?redis在linux上的客戶端
Redis-sentinel? ?? ? redis-sentinel是集群管理工具,主要負責(zé)主從切換。
Redis-server? ?? ?? ?Redis服務(wù)器的daemon啟動程序
2、安裝php的redis擴展
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[iyunv@redis ~]# wget -c -t 0?https://github.com/owlient/phpredis/archive/master.zip
[iyunv@redis ~]# unzip master.zip
[iyunv@redis ~]# cd phpredis-master/
[iyunv@redis?phpredis-master]# phpize
[iyunv@redis phpredis-master]# ./configure --with-php-config=/usr/bin/php-config
[iyunv@redis phpredis-master]# make && make install
#修改php的配置文件,如果沒有“extension=redis.so”,就加上這一行
[iyunv@redis ~]# vim /etc/php.ini
extension=redis.so
[iyunv@redis ~]# /etc/init.d/php-fpm restart
停止 php-fpm:? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?[確定]
正在啟動?php-fpm:? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ???[確定]
3、是否安裝成功
還是訪問phpinfo的那個界面
看到這個就是安裝完成了。
五、讀寫分離
這里只是簡單的做了一下讀,沒有寫操作的相關(guān)代碼,過一會測試,直接到數(shù)據(jù)庫里執(zhí)行update來模擬寫操作。
1、在mysql中插入一些測試數(shù)據(jù)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[iyunv@redis ~]# mysql -u root -p123456
mysql> create database mytest;
mysql> CREATE TABLE `test` (`id` int(7) NOT NULL AUTO_INCREMENT, `name` char(8) DEFAULT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8;
mysql> INSERT INTO `test` VALUES (1,'sven'),(2,'jim'),(3,'zhu'),(4,'wang'),(5,'ftd'),(6,'test'),(7,'test01'),(8,'test02'),(9,'test03');
mysql> select * from mytest.test;
+----+--------+
| id | name? ?|
+----+--------+
|??1 | sven? ?|
|??2 | jim? ? |
|??3 | zhu? ? |
|??4 | wang? ?|
|??5 | ftd? ? |
|??6 | test? ?|
|??7 | test01 |
|??8 | test02 |
|??9 | test03 |
+----+--------+
2、編寫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
37
38
39
40
$redis = new Redis();
$redis->connect('127.0.0.1',6379) or die ("could net connect redis?server");
$query = "select * from test limit 8";
//為了簡單一點,這里就讀取了8條數(shù)據(jù)
for ($key = 1; $key < 9; $key++)
{
if (!$redis->get($key))
{
$connect = mysql_connect('127.0.0.1','root','123456');
mysql_select_db(mytest);
$result = mysql_query($query);
//如果沒有找到$key,就將該查詢sql的結(jié)果緩存到redis
while ($row = mysql_fetch_assoc($result))
{
$redis->set($row['id'],$row['name']);
}
$myserver = 'mysql';
break;
}
else
{
$myserver = "redis";
$data[$key] = $redis->get($key);
}
}
echo $myserver;
echo "
";
for ($key = 1; $key < 9; $key++)
{
echo "number is $key";
echo "
";
echo "name is $data[$key]";
echo "
";
}
?>
第一次訪問,redis中沒有對應(yīng)的KEY時
再次訪問,此時redis中已有相關(guān)數(shù)據(jù)
到這里,我們已經(jīng)實現(xiàn)了redis作為mysql的緩存服務(wù)器,但是如果更新了mysql,redis中仍然會有對應(yīng)的KEY,數(shù)據(jù)就不會更新,此時就會出現(xiàn)mysql和redis數(shù)據(jù)不一致的情況。所以接下來就要通過mysql觸發(fā)器將改變的數(shù)據(jù)同步到redis中。
六、通過gearman實現(xiàn)同步
1、介紹
Gearman是一個支持分布式的任務(wù)分發(fā)框架:
Gearman Job Server:Gearman核心程序,需要編譯安裝并以守護進程形式運行在后臺。
Gearman Client:可以理解為任務(wù)的請求者。
Gearman Worker:任務(wù)的真正執(zhí)行者,一般需要自己編寫具體邏輯并通過守護進程方式運行,Gearman Worker接收到Gearman Client傳遞的任務(wù)內(nèi)容后,會按順序處理。
大致流程:
下面要編寫的mysql觸發(fā)器,就相當于Gearman的客戶端。修改表,插入表就相當于直接下發(fā)任務(wù)。然后通過lib_mysqludf_json UDF庫函數(shù)將關(guān)系數(shù)據(jù)映射為JSON格式,然后在通過gearman-mysql-udf插件將任務(wù)加入到Gearman的任務(wù)隊列中,最后通過redis_worker.php,也就是Gearman的worker端來完成redis數(shù)據(jù)庫的更新。
2、安裝啟動
1
2
3
4
5
[iyunv@redis ~]# yum -y install gearmand libgearman-devel
[iyunv@redis ~]# /etc/init.d/gearmand start
正在啟動 gearmand:? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? [確定]
[iyunv@redis ~]# /etc/init.d/gearmand status
gearmand (pid??7702) 正在運行...
3、安裝php的gearman擴展
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[iyunv@redis ~]# wget -c -t 0?https://pecl.php.net/get/gearman-1.1.1.tgz
[iyunv@redis ~]# tar xvf gearman-1.1.1.tgz
[iyunv@redis ~]# cd gearman-1.1.1
[iyunv@redis gearman-1.1.1]# phpize
[iyunv@redis gearman-1.1.1]# ./configure --with-php-config=/usr/bin/php-config
[iyunv@redis gearman-1.1.1]# make
[iyunv@redis gearman-1.1.1]# make install
#如果php的配置文件中沒有extension = gearman.so,就加上此行
[iyunv@redis ~]# vim /etc/php.ini
extension = gearman.so
[iyunv@redis ~]# /etc/init.d/php-fpm restart
停止 php-fpm:? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?[確定]
正在啟動?php-fpm:? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ???[確定]
這樣就是安裝成功了
4、安裝lib_mysqludf_json
lib_mysqludf_json UDF庫函數(shù)將關(guān)系數(shù)據(jù)映射為JSON格式。通常,數(shù)據(jù)庫中的數(shù)據(jù)映射為JSON格式,是通過程序來轉(zhuǎn)換的。
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
[iyunv@redis ~]# wget -c -t 0?https://github.com/mysqludf/lib_mysqludf_json/archive/master.zip
[iyunv@redis ~]# unzip master.zip
[iyunv@redis ~]# cd lib_mysqludf_json-master/
[iyunv@redis lib_mysqludf_json-master]# gcc $(mysql_config --cflags) -shared -fPIC -o lib_mysqludf_json.so lib_mysqludf_json.c
lib_mysqludf_json.c:40:23: 錯誤:my_global.h:沒有那個文件或目錄
lib_mysqludf_json.c:41:20: 錯誤:my_sys.h:沒有那個文件或目錄
lib_mysqludf_json.c:43:19: 錯誤:mysql.h:沒有那個文件或目錄
lib_mysqludf_json.c:44:21: 錯誤:m_ctype.h:沒有那個文件或目錄
lib_mysqludf_json.c:45:22: 錯誤:m_string.h:沒有那個文件或目錄
#這里編譯報錯是因為沒有安裝mysql的開發(fā)包,如果是源碼安裝的mysql,需要在/etc/ld.so.conf.d/
#目錄下新建一個文件告訴系統(tǒng)mysql的頭文件在哪里
[iyunv@redis lib_mysqludf_json-master]# yum -y install mysql-devel
[iyunv@redis lib_mysqludf_json-master]# gcc $(mysql_config --cflags) -shared -fPIC -o lib_mysqludf_json.so lib_mysqludf_json.c
mysql> show global variables like 'plugin_dir';
+---------------+-------------------------+
| Variable_name | Value? ?? ?? ?? ?? ?? ? |
+---------------+-------------------------+
| plugin_dir? ? | /usr/lib64/mysql/plugin |
+---------------+-------------------------+
#將模塊拷貝到插件目錄下
[iyunv@redis lib_mysqludf_json-master]# cp lib_mysqludf_json.so /usr/lib64/mysql/plugin/
#注冊UDF函數(shù)
mysql> CREATE FUNCTION json_object RETURNS STRING SONAME 'lib_mysqludf_json.so';
5、安裝gearman-mysql-udf
這個插件是用來管理調(diào)用 Gearman 的分布式的隊列。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
[iyunv@redis ~]# wget -c -t 0?https://launchpad.net/gearman-my ... ysql-udf-0.6.tar.gz
[iyunv@redis ~]# tar xvf gearman-mysql-udf-0.6.tar.gz
[iyunv@redis ~]# cd gearman-mysql-udf-0.6
[iyunv@redis gearman-mysql-udf-0.6]# ./configure --with-mysql=/usr/bin/mysql_config --libdir=/usr/lib64/mysql/plugin/
[iyunv@redis gearman-mysql-udf-0.6]# make
[iyunv@redis gearman-mysql-udf-0.6]# make install
#注冊UDF函數(shù)
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';
#查看函數(shù)
mysql> select * from mysql.func;
+--------------------+-----+-------------------------+----------+
| name? ?? ?? ?? ?? ?| ret | dl? ?? ?? ?? ?? ?? ?? ? | type? ???|
+--------------------+-----+-------------------------+----------+
| json_object? ?? ???|? ?0 | lib_mysqludf_json.so? ? | function |
| gman_do_background |? ?0 | libgearman_mysql_udf.so | function |
| gman_servers_set? ?|? ?0 | libgearman_mysql_udf.so | function |
+--------------------+-----+-------------------------+----------+
#指定gearman的服務(wù)信息
mysql> SELECT gman_servers_set('127.0.0.1:4730');
6、編寫mysql觸發(fā)器(根據(jù)實際情況編寫)
1
2
3
4
5
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 ;
7、編寫gearman的worker端
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
[iyunv@redis ~]# vim /www/redis_worker.php
$worker = new GearmanWorker();
$worker->addServer();
$worker->addFunction('syncToRedis', 'syncToRedis');
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
while($worker->work());
function syncToRedis($job)
{
global $redis;
$workString = $job->workload();
$work = json_decode($workString);
if(!isset($work->id)){
return false;
}
$redis->set($work->id, $work->name);
}
?>
#后臺運行
[iyunv@redis www]# nohup?php?redis_worker.php &
"$redis->set($work->id, $work->name);"這條語句就是將id作KEY和name作VALUE分開存儲,需要和前面寫的php測試代碼的存取一致。
8、更新mysql中的數(shù)據(jù)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
mysql> set @RECV = 1;
mysql> select @RECV;
+------+
| @RECV|
+------+
|? ? 1 |
+------+
mysql> update test set name = 'ssss' where id = 1;
mysql> select @RECV;
+------+
| @RECV|
+------+
| NULL |
+------+
從返回值可以看到,觸發(fā)器是觸發(fā)成功的(這里的@RECV是上面mysql TIGGER的返回值)。我們在redis中查看數(shù)據(jù):
1
2
3
[iyunv@redis redis]# ./redis-cli
127.0.0.1:6379> get 1
"sven"
這里的數(shù)據(jù)居然沒有變化,這是我們就要排錯了。
1
2
3
4
5
6
7
8
9
10
11
[iyunv@redis ~]# vim /var/log/audit/audit.log
type=AVC msg=audit(1427807674.425:107): avc:??denied??{ name_connect } for??pid=12453 comm="mysqld" dest=4730 scontext=unconfined_u:system_r:mysqld_t:s0 tcontext=system_u:o
bject_r:port_t:s0 tclass=tcp_socket
#看到這樣一條日志,就知道是selinux阻止了同步
#現(xiàn)在將selinux的模式調(diào)成Permissive
[iyunv@redis ~]# getenforce
Enforcing
[iyunv@redis ~]# setenforce 0
[iyunv@redis ~]# getenforce
Permissive
設(shè)置完成以后,再次執(zhí)行update,進入redis進行查看
1
2
127.0.0.1:6379> get 1
"ssss"
刷新一下剛剛的php界面
到這里就基本算是大功告成了,只要application將數(shù)據(jù)寫到mysql中,mysql觸發(fā)器檢測到更新,就會通過Gearman將
總結(jié)
以上是生活随笔為你收集整理的mysql 5.1.17 redis_redis作为mysql的缓存服务器(读写分离)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 10048 mysql_MySQL 的
- 下一篇: mysql重装远程服务未_CentOS