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 中。