redis+mysql 實現lamp緩存

fastcgi與cgi簡單區別參考:https://www.jianshu.com/p/0cdaa89eeb7a

主從複製的特點:不實時 一定有延遲 網絡因素 數據庫sql性能 主 多線程 io上有複製延遲 從 默認爲單線程

fastcgi與cgi的區別:
fastCGI有後臺進程 9000端口在後臺 一直運行 請求過來直接解析
cgi:fork一個新的進程進行處理

這個實驗存在的問題是數據不同步 除非清除redis的緩存,讓redis再去請求mysql取數據
或者在做update時,在redis中刪除數據 ,但是所以最好的方式是在mysql中做觸發(下一篇博客gearman會寫到)
異步同步

數據流向,分爲兩種情況:

  • webserver ----> (r/w) redisserver ----> 內置鉤子函數 ----> input ----> mysql
  • webserver ----> r (redisserver cache) <–> w mysql ----> update mysql ----> trigger(觸發器) ----> redisserver
    傳統的 redis只做緩存 用來降低mysql訪問壓力。當客戶端有請求過來時,會判斷客戶端的請求是post還是get,如果爲post—寫 則寫到mysql中,如果爲get—讀 則讀redis的緩存數據 (cache 緩存,數據從mysql裏來)
    此時如果客戶端的請求是修改數據,即 mysql被update(數據被更新)的話, redis和mysql兩者沒同步就會導致數據不一致的問題,
    而redis只有在他的數據過期或沒有緩存的時侯纔會去找mysql拿數據,
    update後 會觸發redisserver

實驗環境

  • rhel7且firewalld和selinux爲stop並且disabled。
主機名(IP) 服務
server1(172.25.11.1) php lamp前端
server2(172.25.11.2) redis(中間的緩存)
server3(172.25.11.3) mysql(w)

實驗步驟

server1(lamp)

  • 安裝lamp架構需要的軟件,開啓httpd服務。
[root@server1 ~]# yum install httpd php php-mysql -y
[root@server1 ~]# systemctl start httpd
  • 寫一個php文件用於載瀏覽器中測試(這裏是別人寫好的,我們修改兩處,redis服務器的ip和mysql服務器的ip)。
[root@server1 ~]# mv test.php /var/www/html/

[root@server1 ~]# vim /var/www/html/test.php 
[root@server1 ~]# cat /var/www/html/test.php 
<?php
        $redis = new Redis();
        $redis->connect('172.25.11.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.11.3','redis','westos');
                        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>";
        }
?>

在這裏插入圖片描述

  • 加載php的模塊,此時有mysql模塊了,但是還沒有redis。
[root@server1 ~]# php -m   #查看所有
[root@server1 ~]# php -m | grep mysql    #與mysql相關的,有3個
mysql
mysqli
pdo_mysql
[root@server1 ~]# php -m | grep redis   #與redis相關的,不存在。
  • 所以我們下載php有關redis的壓縮包,解壓(安裝php的redis擴展)。
lftp 172.25.11.250:/pub/redis> get phpredis-master.zip 
[root@server1 ~]# yum install unzip -y
[root@server1 ~]# unzip phpredis-master.zip

在這裏插入圖片描述

  • 進入解壓後的目錄下,加載php的模塊,發現報錯了,這是因爲我們缺少php的依賴包,我們下載並安裝。
    注意:phpize是一個運行腳本,主要作用是檢測php的環境還有就是在特定的目錄生成相應的configure文件,這樣makeinstall之後,生成的.so文件纔會自動加載到php擴展目錄下面。
[root@server1 ~]# cd phpredis-master
[root@server1 phpredis-master]# ls
[root@server1 phpredis-master]# phpize 
lftp 172.25.11.250:/pub/redis> get php-devel-5.4.16-42.el7.x86_64.rpm 
[root@server1 phpredis-master]# yum install php-devel-5.4.16-42.el7.x86_64.rpm -y

在這裏插入圖片描述

  • 再次加載,發現加載成功。
[root@server1 phpredis-master]# phpize 

在這裏插入圖片描述

  • 編譯並安裝,編譯時加上激活redis的參數選項。
[root@server1 phpredis-master]# ./configure --enable-redis
[root@server1 phpredis-master]# make && make install

在這裏插入圖片描述

  • 按照提示,安裝完成後生成的模塊都在此目錄下。
    在這裏插入圖片描述
  • 修改php的初始化文件,修改時區爲上海。
[root@server1 modules]# vim /etc/php.ini
 878 date.timezone = Asia/Shanghai
  • 拷貝mysql的初始化文件,修改內容爲redis的模塊名,加載redis模塊。
[root@server1 modules]# cd /etc/php.d/
[root@server1 php.d]# cp mysql.ini redis.ini
[root@server1 php.d]# vim redis.ini 
[root@server1 php.d]# cat redis.ini 
extension=redis.so
  • 重啓httpd,再次查看與redis有關的模塊,發現成功加載。
[root@server1 php.d]# systemctl restart httpd
[root@server1 php.d]# ps ax
[root@server1 php.d]# php -m | grep redis
redis

server2(redis)

  • 部署redis服務。
    具體流程參考本人之前的博客,這裏簡寫。
lftp 172.25.11.250:/pub/redis> get redis-5.0.3.tar.gz 
[root@server2 ~]# tar zxf redis-5.0.3.tar.gz 
[root@server2 ~]# cd redis-5.0.3
[root@server2 redis-5.0.3]# yum install gcc && make && make install
[root@server2 redis-5.0.3]# cd utils/
[root@server2 utils]# ./install_server.sh 
#修改配置文件
[root@server2 init.d]# vim /etc/redis/6379.conf
  70 bind 0.0.0.0
#開啓服務
[root@server2 init.d]# /etc/init.d/redis_6379 status

server3(mysql)

  • 下載mariadb數據庫的服務器端,開啓服務,嘗試登陸。
[root@server3 ~]# yum install mariadb-server -y
[root@server3 ~]# systemctl start mariadb
[root@server3 ~]# mysql

在這裏插入圖片描述

  • 下載並導入test.sql庫。
lftp 172.25.11.250:/pub/redis> get test.sql 
[root@server3 ~]# mysql < test.sql 
  • test.sql文件的內容。
[root@server3 ~]# 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 BEGIN
#    SET @RECV=gman_do_background('syncToRedis', json_object(NEW.id as `id`, NEW.name as `name`)); 
#  END$$
#DELIMITER ;
  • 導入成功後我們查詢一下導入的數據。
MariaDB [(none)]> use test;
MariaDB [test]> select * from test;

在這裏插入圖片描述

  • 給用戶和數據庫授權。
MariaDB [test]> grant all on test.* to redis@'%' identified by 'westos';

測試

  • 在瀏覽器中訪問我們下載的測試頁。
172.25.11.1/test.php
  • 第一次是從mysql中讀取到的數據。(因爲redis中還沒有緩存)
    在這裏插入圖片描述
  • 第二次是在redis數據庫中。(緩存)
    在這裏插入圖片描述
  • 在redis數據庫端查詢數據。
    在這裏插入圖片描述
  • 但是,主從複製存在數據不一致的問題,即當用戶更新mysql數據庫中的數據時,reids端並不能立即同步修改後的數據庫(除非清除緩存或數據過期),用戶此時查詢到的依然是之前的緩存。
#更新數據
MariaDB [test]> update test set name='westos' where id=1;
MariaDB [test]> select * from test;

在這裏插入圖片描述

  • 瀏覽器中訪問的結果依然沒有改變。
    在這裏插入圖片描述
  • 但在如果在redis數據庫清除更新的數據之後,用戶再訪問,數據就會刷新。
  • 第一次,從mysql中讀。
    在這裏插入圖片描述
  • 第二次,從redis中讀,可以看到數據已經同步,讀的是redis的緩存。
    在這裏插入圖片描述
  • 這裏讓兩者同步的辦法是清除redis中的緩存。
    在這裏插入圖片描述
    總結:
    1.這種方式存在明顯的問題:在mysql更新數據數據無法同步到redis上,雖然可以直接在redis中更新,但是在企業中更新的數據雜且多,而數據庫的數據是比較穩定的,如果只在redis上更新,如果redis出現問題,則更新的數據會丟失,這是不可取的。
    2.我們已經實現了 redis 作爲 mysql 的緩存服務器,但是如果更新了 mysql,redis
    中仍然會有對應的 KEY,數據就不會更新,此時就會出現 mysql 和 redis 數據不一致的情
    況。所以接下來就要通過 mysql 觸發器將改變的數據同步到 redis 中。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章