検索
ホームページデータベースmysql チュートリアルredis作为mysql的缓存服务器(读写分离)

redis作为mysql的缓存服务器(读写分离)

Jun 07, 2016 pm 02:55 PM
mysqlreredis分離サーバキャッシュ読み書き

一、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と他のSQL方言の構文の違いは何ですか?MySQLと他のSQL方言の構文の違いは何ですか?Apr 27, 2025 am 12:26 AM

MySQLdiffersfromotherSQLdialectsinsyntaxforLIMIT,auto-increment,stringcomparison,subqueries,andperformanceanalysis.1)MySQLusesLIMIT,whileSQLServerusesTOPandOracleusesROWNUM.2)MySQL'sAUTO_INCREMENTcontrastswithPostgreSQL'sSERIALandOracle'ssequenceandt

MySQLパーティションは何ですか?MySQLパーティションは何ですか?Apr 27, 2025 am 12:23 AM

MySQLパーティション化により、パフォーマンスが向上し、メンテナンスが簡素化されます。 1)大きなテーブルを特定の基準(日付範囲など)、2)物理的に独立したファイルに物理的に分割する、3)MySQLはクエリするときに関連するパーティションに焦点を合わせることができます。

MySQLで特権をどのように許可して取り消しますか?MySQLで特権をどのように許可して取り消しますか?Apr 27, 2025 am 12:21 AM

mysqlで許可を許可および取り消す方法は? 1。grantallprivilegesondatabase_name.to'username'@'host 'などの許可を付与するために付与ステートメントを使用してください。 2。Revokeallprivilegesondatabase_name.from'username'@'host 'など、Revoke Statementを使用して、許可のタイムリーな通信を確保します。

InnoDBとMyisamストレージエンジンの違いを説明してください。InnoDBとMyisamストレージエンジンの違いを説明してください。Apr 27, 2025 am 12:20 AM

INNODBは、トランザクションサポートと高い並行性を必要とするアプリケーションに適していますが、Myisamはより多くの読み取りとより少ない書き込みを必要とするアプリケーションに適しています。 1.INNODBは、eコマースおよび銀行システムに適したトランザクションおよび銀行レベルのロックをサポートしています。 2. Myisamは、ブログやコンテンツ管理システムに適した、迅速な読み取りとインデックス作成を提供します。

MySQLの結合のさまざまなタイプは何ですか?MySQLの結合のさまざまなタイプは何ですか?Apr 27, 2025 am 12:13 AM

MySQLには4つのメイン結合タイプがあります:innerjoin、leftjoin、rightjoin、fullouterjoin。 1.InnerJoinは、結合条件を満たす2つのテーブルのすべての行を返します。 2.右のテーブルに一致する行がない場合でも、Leftjoinは左のテーブルのすべての行を返します。 3。右joinはleftjoinに反しており、右のテーブルのすべての行を返します。 4.fullouterjoinは、結合条件を満たしている、または満たさない2つのテーブルのすべての行を返します。

MySQLで利用可能なさまざまなストレージエンジンは何ですか?MySQLで利用可能なさまざまなストレージエンジンは何ですか?Apr 26, 2025 am 12:27 AM

mysqloffersvariousstorageEngines、それぞれのfordifferentusecases:1)Innodbisidealforapplicationsingingidcomplianceanceandhighconcurrency、support transactions andforeignkeys.2)myisamisbestforread-havyworkloads、transactionsupptort.3)

MySQLの一般的なセキュリティの脆弱性は何ですか?MySQLの一般的なセキュリティの脆弱性は何ですか?Apr 26, 2025 am 12:27 AM

MySQLの一般的なセキュリティの脆弱性には、SQLインジェクション、弱いパスワード、不適切な許可構成、および非合事ソフトウェアが含まれます。 1。SQL注射は、前処理ステートメントを使用することで防ぐことができます。 2。強力なパスワード戦略を強制的に使用することにより、弱いパスワードを回避できます。 3.不適切な許可構成は、ユーザー許可の定期的なレビューと調整を通じて解決できます。 4.未使用のソフトウェアは、MySQLバージョンを定期的にチェックして更新することでパッチを適用できます。

MySQLでスロークエリをどのように識別できますか?MySQLでスロークエリをどのように識別できますか?Apr 26, 2025 am 12:15 AM

MySQLの遅いクエリを識別することは、遅いクエリログを有効にし、しきい値を設定することで実現できます。 1.スロークエリログを有効にし、しきい値を設定します。 2.スロークエリログファイルを表示および分析し、詳細な分析のためにMySQLDumpSlowやPT-Query-Digestなどのツールを使用します。 3.インデックスの最適化、クエリの書き換え、およびselect*の使用を回避することで、遅いクエリの最適化を実現できます。

See all articles

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

AtomエディタMac版ダウンロード

AtomエディタMac版ダウンロード

最も人気のあるオープンソースエディター

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

WebStorm Mac版

WebStorm Mac版

便利なJavaScript開発ツール

DVWA

DVWA

Damn Vulnerable Web App (DVWA) は、非常に脆弱な PHP/MySQL Web アプリケーションです。その主な目的は、セキュリティ専門家が法的環境でスキルとツールをテストするのに役立ち、Web 開発者が Web アプリケーションを保護するプロセスをより深く理解できるようにし、教師/生徒が教室環境で Web アプリケーションを教え/学習できるようにすることです。安全。 DVWA の目標は、シンプルでわかりやすいインターフェイスを通じて、さまざまな難易度で最も一般的な Web 脆弱性のいくつかを実践することです。このソフトウェアは、