Redis + MySql + Nginx 的整合使用

實驗環境:

server1   172.25.254.1      做nginx,用戶訪問的入口
server2   172.25.254.2		做redis,緩存數據
server3   172.25.254.3		做mysql,真實存儲數據

原理:

用 redis 用來緩存熱點數據,來降低mysql的訪問壓力,80%的訪問都集中在20%的數據上,所以我們把這20%的數據放到 redis 中。

訪問流程:

client --> app(tomcat..) --> redis -> mysql -> redis -> client
如果redis中沒有,就先取mysql中緩存到redis中,在從redis中讀取,返回給客戶端

redis從Mysql中緩存

server1中:

我們編譯安裝nginx-1.18,

vim auto/cc/gcc
在裏面註釋掉dubug,使安裝更小更快
yum install -y pcre-devel         安裝依賴性
yum install zlib-devel -y
./configure --prefix=/usr/local/nginx    預編譯
make && make install

配置一下:nginx.conf
在這裏插入圖片描述
在這裏插入圖片描述
打開php功能模塊.

/usr/local/nginx/sbin/nginx    啓動

測試訪問:
在這裏插入圖片描述
配置一個php頁面,
在這裏插入圖片描述
但是我們當前不能解析php,我們需要去配置php的一些插件:

在這裏插入圖片描述
yum install 安裝。
在這裏插入圖片描述
啓動php,9000端口和80端口打開
測試訪問php頁面:
在這裏插入圖片描述
訪問成功,更改index.php文件內容爲:

<?php
        $redis = new Redis();
        $redis->connect('172.25.254.2',6379) or die ("could net connect redis server");
  #      $query = "select * from test limit 9";
        $query = "select * from test";
        for ($key = 1; $key < 10; $key++)
        {
                if (!$redis->get($key))
                {
                        $connect = mysql_connect('172.25.254.3','redis','caoaoyuan');
                        mysql_select_db(test);
                        $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 < 10; $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>";
        }
?>

server2中:

配置redis,並啓動。

server3中:

安裝mariadb,並啓動。

yum install -y mariadb-server
systemctl start mariadb.service

登陸數據庫,

MariaDB [(none)]> create database test;
Query OK, 1 row affected (0.00 sec)
#創建一個test的表,因爲我們server1上index.php 訪問的就是test的表,可去上面查看

MariaDB [(none)]> grant all on test.* to redis@'%' identified by 'caoaoyuan';
Query OK, 0 rows affected (0.00 sec)
#授權用戶

MariaDB [(none)]> flush privileges;
Query OK, 0 rows affected (0.00 sec)
#刷新授權表

測試

我們給數據庫導入一些數據進行測試

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 BEGIN
#    SET @RECV=gman_do_background('syncToRedis', json_object(NEW.id as `id`, NEW.name as `name`));
#  END$$
#DELIMITER ;
mysql -pcaoaoyuan < test.sql      導入

訪問:
在這裏插入圖片描述
代表這些數據時從mysql獲取的,我們在刷新一次:
在這裏插入圖片描述
就說明這些數據時從redis獲取的,說明第一次將數據存儲到了redis,第二次直接從redis中讀取。
而且:
在這裏插入圖片描述
我們的redis剛纔是沒有數據的,這時可以獲取到緩存的數據了。

如果Mysql中的數據進行了變更,這時我們redis的數據會不會同時更新那?

MariaDB [test]> update test set name='westos' where id=1;
Query OK, 1 row affected (0.04 sec)
Rows matched: 1  Changed: 1  Warnings: 0
更新數據

訪問:
在這裏插入圖片描述
在這裏插入圖片描述
沒有更新。除非我們手動更新。

redis 同步mysql

所以我們應定時同步mysql的數據。這時我們用到了gearmand服務。使用udf的方式。
在server1中:
在這裏插入圖片描述
我們在server3數據庫中配置,當數據更新時會觸發觸發器,觸發器會觸發mysql中的 udf(user defined function) 插件,這個擦件會調用gearman的服務。它會調用 worker 再通過worker 調用php-pecl-redis,從而把數據同步到redis中。

一個由Gearman驅動的應用程序由三部分組成:一個客戶端、一個worker和一個job服務器。客戶端負責創建要運行的作業並將其發送到作業服務器。作業服務器將找到一個合適的工作者,可以運行作業並轉發作業。worker執行客戶機請求的工作,並通過作業服務器向客戶機發送響應。Gearman提供了客戶端和工作者api,您的應用程序可以調用這些api與Gearman作業服務器(也稱爲gearmand)進行對話,因此您不需要處理作業的聯網或映射。在內部,gearman客戶端和工作api使用TCP套接字與作業服務器進行通信。

我們的server1就相當於job服務器,用來分發任務,在server3充當客戶端。

啓動服務,會開啓一個4730的端口
在這裏插入圖片描述
server3中:
安裝插件,

yum install mariadb-devel.x86_64 -y          否則不支持 udf

在這裏插入圖片描述
編譯這個用戶自定義函數:

gcc $(mysql_config --cflags) -shared -fPIC -o lib_mysqludf_json.so lib_mysqludf_json.c
cp lib_mysqludf_json.so /usr/lib64/mysql/plugin/
把它放到數據庫的默認插件目錄中去。

現在我們註冊剛纔編譯的 udf函數,我們創建一個json對象,把數據全部映射爲json格式,因爲json格式可讀性比較強。

MariaDB [(none)]> CREATE FUNCTION json_object RETURNS STRING SONAME 'lib_mysqludf_json.so';
Query OK, 0 rows affected (0.00 sec)
yum install libevent-devel-2.0.21-4.el7.x86_64.rpm libgearman-1.1.12-18.el7.x86_64.rpm libgearman-devel-1.1.12-18.el7.x86_64.rpm -y
安裝一些gearman的庫文件和依賴性

編譯安裝gearman-mysql-udf插件:
在這裏插入圖片描述

./configure --libdir=/usr/lib64/mysql/plugin --with-mysql
make && make install

這樣我們就在server3中安裝好了需要的插件。
註冊udf函數的插件。

 CREATE FUNCTION gman_do_background RETURNS STRING SONAME 'libgearman_mysql_udf.so';
 CREATE FUNCTION gman_servers_set RETURNS STRING SONAME 'libgearman_mysql_udf.so';

在這裏插入圖片描述
總體就是這三個函數。
查找服務:
在這裏插入圖片描述
然後我們需要去創建觸發器。
在這裏插入圖片描述
與上次不同。
導入到mysql;

[root@server3 ~]# mysql -pcaoaoyuan < test.sql 

在這裏插入圖片描述
這就是我們剛定義的觸發器。

現在我們在server1中去配置worker端,誰去執行這個同步的任務。

vim worker.php
<?php
$worker = new GearmanWorker();
$worker->addServer();
$worker->addFunction('syncToRedis', 'syncToRedis');

$redis = new Redis();
$redis->connect('172.25.254.2', 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@server1 rhel7]# cp worker.php /usr/local/

我們可以直接用php執行,這個進程會一直運行worker.php,會一直從redis中同步數據
[root@server1 rhel7]# nohup php /usr/local/worker.php &> /dev/null & 
[1] 9080

測試:
在server3中:

# 更新數據
MariaDB [test]> update test set name='westos' where id=2;
Query OK, 1 row affected (0.29 sec)
Rows matched: 1  Changed: 1  Warnings: 0
# 查看
MariaDB [test]> select * from test;
+----+--------+
| id | name   |
+----+--------+
|  1 | westos |
|  2 | westos |
|  3 | test3  |
|  4 | test4  |
|  5 | test5  |
|  6 | test6  |
|  7 | test7  |
|  8 | test8  |
|  9 | test9  |
+----+--------+

然後我們測試訪問:
在這裏插入圖片描述
就同步成功了。1不會更新,開啓gearman後 2就更新了

  • 原理
  • mysql的變更觸發 trigger ,然後 json_map插件,將變更格式化爲json格式,
  • 然後找到 mysql 的 gearman 和 udf 的插件 ,然後找到 gearman(job-server / server1)
  • 然後 jojb-server 將任務分發給 worker。
  • worker 就和 php-gearman 和 php-redis 通信,將數據同步到server2上的 redis,redis 再發送到客戶端,同時同步到本地緩存。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章