搜索
首页数据库mysql教程redis作为mysql的缓存服务器(读写分离)

一、redis简介 Redis是一个key-value存储系统。和Memcached类似,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。在部分场合可以对关系

一、redis简介

Redis是一个key-value存储系统。和Memcached类似,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。在部分场合可以对关系数据库起到很好的补充作用。它提供了Java,C/C++(hiredis),C#,PHP,JavaScript,Perl,Object-C,Python,Ruby等客户端,使用很方便。


二、架构图

wKioL1UaFsii5Z8qAADOf7iND80904.jpg

大致结构就是读写分离,将mysql中的数据通过触发器同步到redis中


三、安装LNMP环境(这里为了省事,就是用yum来安装)

1、修改yum源

[root@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安装

 [root@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

[root@redis ~]# vim /etc/nginx/nginx.conf
server {
        listen       80;
        #定义使用www.xx.com访问
        server_name  www.xx.com;

        #设定本虚拟主机的访问日志
        access_log  /logs/www.xx.com.access.log  main;

        #默认请求
        location / {
          root   /www/;      #定义服务器的默认网站根目录位置
          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、启动服务

[root@redis ~]# sed -i 's/apache/nginx/g' /etc/php-fpm.d/www.conf
[root@redis ~]# /etc/init.d/php-fpm start
正在启动 php-fpm:                                         [确定]

[root@redis ~]# /etc/init.d/mysqld start
正在启动 mysqld:                                          [确定]

[root@redis ~]# mkdir /{logs,www}
[root@redis ~]# chown -R nginx:nginx /{logs,www}
[root@redis ~]# /etc/init.d/nginx start
正在启动 nginx:                                           [确定]

[root@redis www]# service iptables stop
iptables: Flushing firewall rules:                         [  OK  ]
iptables: Setting chains to policy ACCEPT: filter          [  OK  ]
iptables: Unloading modules:                               [  OK  ]

[root@redis redis]# netstat -tnlp      #查看监听
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授权

[root@redis ~]# mysql
mysql> grant all privileges on *.* to root@localhost identified by '123456';

mysql> flush privileges;


6、测试

[root@redis ~]# vim /www/index.php 
<?php
     phpinfo();
?>

然后访问页面看到php的相关信息,基础环境就算搭建完成了。


四、安装redis

1、安装redis

[root@redis ~]# wget -c -t 0 http://download.redis.io/releases/redis-2.8.19.tar.gz
 
[root@redis ~]# mkdir /usr/local/redis

[root@redis ~]# tar xvf redis-2.8.19.tar.gz 
#安装很简单、直接make就可以了
[root@redis ~]# cd redis-2.8.19
[root@redis redis-2.8.19]# make 

#编译完成后,将src中的可执行文件拷贝到刚刚创建的目录中
[root@redis src]# cp redis-benchmark redis-check-aof redis-check-dump redis-cli redis-sentinel redis-server /usr/local/redis/
[root@redis redis-2.8.19]# cp redis.conf sentinel.conf /usr/local/redis/

Redis-benchmark      压力测试工具

Redis-check-aof      检查redis持久化命令文件的完整性

Redis-check-dump     检查redis持久化数据文件的完整性

Redis-cli            redis在linux上的客户端

Redis-sentinel       redis-sentinel是集群管理工具,主要负责主从切换。

Redis-server         Redis服务器的daemon启动程序


2、安装php的redis扩展

[root@redis ~]# wget -c -t 0 https://github.com/owlient/phpredis/archive/master.zip
[root@redis ~]# unzip master.zip

[root@redis ~]# cd phpredis-master/
[root@redis phpredis-master]# phpize 
[root@redis phpredis-master]# ./configure --with-php-config=/usr/bin/php-config
[root@redis phpredis-master]# make && make install 

#修改php的配置文件,如果没有“extension=redis.so”,就加上这一行
[root@redis ~]# vim /etc/php.ini 
extension=redis.so

[root@redis ~]# /etc/init.d/php-fpm restart
停止 php-fpm:                                             [确定]
正在启动 php-fpm:                                         [确定]


3、是否安装成功

还是访问phpinfo的那个界面

wKioL1UaEDeBJuP3AABbp2hjrt4347.jpg

看到这个就是安装完成了。


五、读写分离

这里只是简单的做了一下读,没有写操作的相关代码,过一会测试,直接到数据库里执行update来模拟写操作。

1、在mysql中插入一些测试数据

[root@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的测试代码

<?php
        $redis = new Redis();
        $redis->connect('127.0.0.1',6379) or die ("could net connect redis server");
        $query = "select * from test limit 8";
        //为了简单一点,这里就读取了8条数据
        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的结果缓存到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 "<br>";
        for ($key = 1; $key < 9; $key++)
        {
                echo "number is <b><font color=#FF0000>$key</font></b>";

                echo "<br>";

                echo "name is <b><font color=#FF0000>$data[$key]</font></b>";

                echo "<br>";
        }
?>

第一次访问,redis中没有对应的KEY时

wKiom1UaIrjC3shWAAD2e_5hT48678.jpg

再次访问,此时redis中已有相关数据

wKiom1UaIuTxTtn2AAEcXGxJop8634.jpg

到这里,我们已经实现了redis作为mysql的缓存服务器,但是如果更新了mysql,redis中仍然会有对应的KEY,数据就不会更新,此时就会出现mysql和redis数据不一致的情况。所以接下来就要通过mysql触发器将改变的数据同步到redis中。


六、通过gearman实现同步

1、介绍

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、安装启动

[root@redis ~]# yum -y install gearmand libgearman-devel
[root@redis ~]# /etc/init.d/gearmand start
正在启动 gearmand:                                        [确定]
[root@redis ~]# /etc/init.d/gearmand status
gearmand (pid  7702) 正在运行...


3、安装php的gearman扩展

[root@redis ~]# wget -c -t 0 https://pecl.php.net/get/gearman-1.1.1.tgz
 
[root@redis ~]# tar xvf gearman-1.1.1.tgz 
[root@redis ~]# cd gearman-1.1.1
[root@redis gearman-1.1.1]# phpize 
[root@redis gearman-1.1.1]# ./configure --with-php-config=/usr/bin/php-config
[root@redis gearman-1.1.1]# make 
[root@redis gearman-1.1.1]# make install

#如果php的配置文件中没有extension = gearman.so,就加上此行
[root@redis ~]# vim /etc/php.ini 
extension = gearman.so
[root@redis ~]# /etc/init.d/php-fpm restart
停止 php-fpm:                                             [确定]
正在启动 php-fpm:                                         [确定]

wKiom1UaJ1HheqvfAAC0WqZjDCQ519.jpg

这样就是安装成功了


4、安装lib_mysqludf_json

lib_mysqludf_json UDF库函数将关系数据映射为JSON格式。通常,数据库中的数据映射为JSON格式,是通过程序来转换的。

[root@redis ~]# wget -c -t 0 https://github.com/mysqludf/lib_mysqludf_json/archive/master.zip
[root@redis ~]# unzip master.zip 
[root@redis ~]# cd lib_mysqludf_json-master/
[root@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的开发包,如果是源码安装的mysql,需要在/etc/ld.so.conf.d/
#目录下新建一个文件告诉系统mysql的头文件在哪里
[root@redis lib_mysqludf_json-master]# yum -y install mysql-devel
[root@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 |
+---------------+-------------------------+

#将模块拷贝到插件目录下
[root@redis lib_mysqludf_json-master]# cp lib_mysqludf_json.so /usr/lib64/mysql/plugin/

#注册UDF函数
mysql> CREATE FUNCTION json_object RETURNS STRING SONAME 'lib_mysqludf_json.so';


5、安装gearman-mysql-udf

这个插件是用来管理调用 Gearman 的分布式的队列。 

[root@redis ~]# wget -c -t 0 https://launchpad.net/gearman-mysql-udf/trunk/0.6/+download/gearman-mysql-udf-0.6.tar.gz
[root@redis ~]# tar xvf gearman-mysql-udf-0.6.tar.gz

[root@redis ~]# cd gearman-mysql-udf-0.6
[root@redis gearman-mysql-udf-0.6]# ./configure --with-mysql=/usr/bin/mysql_config --libdir=/usr/lib64/mysql/plugin/
[root@redis gearman-mysql-udf-0.6]# make 
[root@redis gearman-mysql-udf-0.6]# make install

#注册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;
+--------------------+-----+-------------------------+----------+
| 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的服务信息
mysql> SELECT gman_servers_set('127.0.0.1:4730');


6、编写mysql触发器(根据实际情况编写)

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端

[root@redis ~]# vim /www/redis_worker.php
<?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);
}
?>

#后台运行
[root@redis www]# nohup php redis_worker.php &

"$redis->set($work->id, $work->name);"这条语句就是将id作KEY和name作VALUE分开存储,需要和前面写的php测试代码的存取一致。


8、更新mysql中的数据

mysql> set @RECV = 1;
mysql> select @RECV;
+------+
| @RECV|
+------+
|    1 |
+------+
mysql> update test set name = 'ssss' where id = 1;
mysql> select @RECV;
+------+
| @RECV|
+------+
| NULL |
+------+

从返回值可以看到,触发器是触发成功的(这里的@RECV是上面mysql TIGGER的返回值)。我们在redis中查看数据:

[root@redis redis]# ./redis-cli 
127.0.0.1:6379> get 1
"sven"

这里的数据居然没有变化,这是我们就要排错了。

[root@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阻止了同步

#现在将selinux的模式调成Permissive 
[root@redis ~]# getenforce 
Enforcing
[root@redis ~]# setenforce 0
[root@redis ~]# getenforce 
Permissive

设置完成以后,再次执行update,进入redis进行查看

127.0.0.1:6379> get 1
"ssss"

刷新一下刚刚的php界面

wKiom1UaVVfTHNxBAAEJ_PKtNDU910.jpg

到这里就基本算是大功告成了,只要application将数据写到mysql中,mysql触发器检测到更新,就会通过Gearman将数据同步到redis中。然后读取的话,就直接从redis中进行读取。当然这只是个实验环境,实际上还有很多细节要调整。


七、GitHub上的一个有意思的工具

地址:https://github.com/delano/redis-dump

这个工具是用备份的redis的,也许你会问redis有自己的持久化,要这个工具干嘛?

redis的自带的持久化具有局限性,假象我们需要redis回到过去的某个时刻去(回档)。redis自带的持久化要实现这个需求,办法就是不断的将dump文件或者aof文件移动到其他目录中去,不然它就会被新的持久化文件覆盖。

而这个工具,就可以在任意时刻将数据库备份出来,非常方便。

[root@redis ~]# yum -y install rubygems.noarch ruby-devel
[root@redis ~]# gem install redis-dump

这样就安装完成了,使用方法到GitHub上去看,挺详细的。


参考文章:http://avnpc.com/pages/mysql-replication-to-redis-by-gearman

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
如何识别和优化MySQL中的慢速查询? (慢查询日志,performance_schema)如何识别和优化MySQL中的慢速查询? (慢查询日志,performance_schema)Apr 10, 2025 am 09:36 AM

要优化MySQL慢查询,需使用slowquerylog和performance_schema:1.启用slowquerylog并设置阈值,记录慢查询;2.利用performance_schema分析查询执行细节,找出性能瓶颈并优化。

MySQL和SQL:开发人员的基本技能MySQL和SQL:开发人员的基本技能Apr 10, 2025 am 09:30 AM

MySQL和SQL是开发者必备技能。1.MySQL是开源的关系型数据库管理系统,SQL是用于管理和操作数据库的标准语言。2.MySQL通过高效的数据存储和检索功能支持多种存储引擎,SQL通过简单语句完成复杂数据操作。3.使用示例包括基本查询和高级查询,如按条件过滤和排序。4.常见错误包括语法错误和性能问题,可通过检查SQL语句和使用EXPLAIN命令优化。5.性能优化技巧包括使用索引、避免全表扫描、优化JOIN操作和提升代码可读性。

描述MySQL异步主奴隶复制过程。描述MySQL异步主奴隶复制过程。Apr 10, 2025 am 09:30 AM

MySQL异步主从复制通过binlog实现数据同步,提升读性能和高可用性。1)主服务器记录变更到binlog;2)从服务器通过I/O线程读取binlog;3)从服务器的SQL线程应用binlog同步数据。

mysql:简单的概念,用于轻松学习mysql:简单的概念,用于轻松学习Apr 10, 2025 am 09:29 AM

MySQL是一个开源的关系型数据库管理系统。1)创建数据库和表:使用CREATEDATABASE和CREATETABLE命令。2)基本操作:INSERT、UPDATE、DELETE和SELECT。3)高级操作:JOIN、子查询和事务处理。4)调试技巧:检查语法、数据类型和权限。5)优化建议:使用索引、避免SELECT*和使用事务。

MySQL:数据库的用户友好介绍MySQL:数据库的用户友好介绍Apr 10, 2025 am 09:27 AM

MySQL的安装和基本操作包括:1.下载并安装MySQL,设置根用户密码;2.使用SQL命令创建数据库和表,如CREATEDATABASE和CREATETABLE;3.执行CRUD操作,使用INSERT,SELECT,UPDATE,DELETE命令;4.创建索引和存储过程以优化性能和实现复杂逻辑。通过这些步骤,你可以从零开始构建和管理MySQL数据库。

InnoDB缓冲池如何工作,为什么对性能至关重要?InnoDB缓冲池如何工作,为什么对性能至关重要?Apr 09, 2025 am 12:12 AM

InnoDBBufferPool通过将数据和索引页加载到内存中来提升MySQL数据库的性能。1)数据页加载到BufferPool中,减少磁盘I/O。2)脏页被标记并定期刷新到磁盘。3)LRU算法管理数据页淘汰。4)预读机制提前加载可能需要的数据页。

MySQL:初学者的数据管理易用性MySQL:初学者的数据管理易用性Apr 09, 2025 am 12:07 AM

MySQL适合初学者使用,因为它安装简单、功能强大且易于管理数据。1.安装和配置简单,适用于多种操作系统。2.支持基本操作如创建数据库和表、插入、查询、更新和删除数据。3.提供高级功能如JOIN操作和子查询。4.可以通过索引、查询优化和分表分区来提升性能。5.支持备份、恢复和安全措施,确保数据的安全和一致性。

与MySQL中使用索引相比,全表扫描何时可以更快?与MySQL中使用索引相比,全表扫描何时可以更快?Apr 09, 2025 am 12:05 AM

全表扫描在MySQL中可能比使用索引更快,具体情况包括:1)数据量较小时;2)查询返回大量数据时;3)索引列不具备高选择性时;4)复杂查询时。通过分析查询计划、优化索引、避免过度索引和定期维护表,可以在实际应用中做出最优选择。

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
3 周前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
3 周前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
3 周前By尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解锁Myrise中的所有内容
3 周前By尊渡假赌尊渡假赌尊渡假赌

热工具

WebStorm Mac版

WebStorm Mac版

好用的JavaScript开发工具

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

SublimeText3 英文版

SublimeText3 英文版

推荐:为Win版本,支持代码提示!

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

DVWA

DVWA

Damn Vulnerable Web App (DVWA) 是一个PHP/MySQL的Web应用程序,非常容易受到攻击。它的主要目标是成为安全专业人员在合法环境中测试自己的技能和工具的辅助工具,帮助Web开发人员更好地理解保护Web应用程序的过程,并帮助教师/学生在课堂环境中教授/学习Web应用程序安全。DVWA的目标是通过简单直接的界面练习一些最常见的Web漏洞,难度各不相同。请注意,该软件中