十年網站開發(fā)經驗 + 多家企業(yè)客戶 + 靠譜的建站團隊
量身定制 + 運營維護+專業(yè)推廣+無憂售后,網站問題一站解決
PHP有自帶的高性能函數(shù) var_export
創(chuàng)新互聯(lián)業(yè)務包括:成品網站、企業(yè)產品展示型網站建設、高端網站設計、電子商務型網站建設、成都外貿網站建設(多語言)、商城建設、按需搭建網站、全網營銷推廣等。效率優(yōu)先,品質保證,用心服務是我們的核心價值觀,我們將繼續(xù)以良好的信譽為基礎,秉承穩(wěn)固與發(fā)展、求實與創(chuàng)新的精神,為客戶提供更全面、更優(yōu)質的互聯(lián)網服務!
conn.php
?php
$dbconfig = array (
'host'='127.0.0.1',
'name'='root',
'password'='123456',
?
b.php
?php
// 讀取配置
include 'conn.php';
echo $dbconfig['host'];
// 修改配置
$dbconfig['host'] = 'xxx.xxx.xxx.xxx';
file_put_contents('conn.php', "?php\n$dbconfig = " . var_export($dbconfig) . "\n?");
// 再讀取配置
include 'conn.php';
echo $dbconfig['host'];
?
參考連接:
是一個文件,用記事本就可以打開,可以在你安裝環(huán)境下的目錄下面找到,例如wamp環(huán)境放在根目錄下的tmp文件夾(臨時內容文件夾)下。
一、全頁面靜態(tài)化緩存
也就是將頁面全部生成html靜態(tài)頁面,用戶訪問時直接訪問的靜態(tài)頁面,而不會去走php服務器解析的流程。此種方式,在CMS系統(tǒng)中比較常見,比如dedecms;
一種比較常用的實現(xiàn)方式是用輸出緩存:
Ob_start()******要運行的代碼*******$content=Ob_get_contents();****將緩存內容寫入html文件*****Ob_end_clean();
二、數(shù)據緩存
顧名思義,就是緩存數(shù)據的一種方式;比如,商城中的某個商品信息,當用商品id去請求時,就會得出包括店鋪信息、商品信息等數(shù)據,此時就可以將這些數(shù)據緩存到一個php文件中,文件名包含商品id來建一個唯一標示;下一次有人想查看這個商品時,首先就直接調這個文件里面的信息,而不用再去數(shù)據庫查詢;其實緩存文件中緩存的就是一個php數(shù)組之類;
Ecmall商城系統(tǒng)里面就用了這種方式;
三、查詢緩存
其實這跟數(shù)據緩存是一個思路,就是根據查詢語句來緩存;將查詢得到的數(shù)據緩存在一個文件中,下次遇到相同的查詢時,就直接先從這個文件里面調數(shù)據,不會再去查數(shù)據庫;但此處的緩存文件名可能就需要以查詢語句為基點來建立唯一標示;
按時間變更進行緩存
就是對于緩存文件您需要設一個有效時間,在這個有效時間內,相同的訪問才會先取緩存文件的內容,但是超過設定的緩存時間,就需要重新從數(shù)據庫中獲取數(shù)據,并生產最新的緩存文件;比如,我將我們商城的首頁就是設置2個小時更新一次。
四、頁面部分緩存
該種方式,是將一個頁面中不經常變的部分進行靜態(tài)緩存,而經常變化的塊不緩存,最后組裝在一起顯示;可以使用類似于ob_get_contents的方式實現(xiàn),也可以利用類似ESI之類的頁面片段緩存策略,使其用來做動態(tài)頁面中相對靜態(tài)的片段部分的緩存。
該種方式可以用于如商城中的商品頁;
五、Opcode緩存
首先php代碼被解析為Tokens,然后再編譯為Opcode碼,最后執(zhí)行Opcode碼,返回結果;所以,對于相同的php文件,第一次運行時可以緩存其Opcode碼,下次再執(zhí)行這個頁面時,直接會去找到緩存下的opcode碼,直接執(zhí)行最后一步,而不再需要中間的步驟了。
比較知名的是XCache、TurckMMCache、PHPAccelerator等。
六、按內容變更進行緩存
這個也并非獨立的緩存技術,需結合著用;就是當數(shù)據庫內容被修改時,即刻更新緩存文件;
比如,一個人流量很大的商城,商品很多,商品表必然比較大,這表的壓力也比較重;我們就可以對商品顯示頁進行頁面緩存;
當商家在后臺修改這個商品的信息時,點擊保存,我們同時就更新緩存文件;那么,買家訪問這個商品信息時,實際問的是一個靜態(tài)頁面,而不需要再去訪問數(shù)據庫;
試想,如果對商品頁不緩存,那么每次訪問一個商品就要去數(shù)據庫查一次,如果有10萬人在線瀏覽商品,那服務器壓力就大了;
七、內存式緩存
提到這個,可能大家想到的首先就是Memcached;memcached是高性能的分布式內存緩存服務器。一般的使用目的是,通過緩存數(shù)據庫查詢結果,減少數(shù)據庫訪問次數(shù),以提高動態(tài)Web應用的速度、提高可擴展性。
它就是將需要緩存的信息,緩存到系統(tǒng)內存中,需要獲取信息時,直接到內存中取;比較常用的方式就是key_value方式;
connect($memcachehost,$memcacheport)ordie("Couldnotconnect");$memcache-set('key','緩存的內容');$get=$memcache-get($key);//獲取信息?
八、apache緩存模塊
apache安裝完以后,是不允許被cache的。昌平鎮(zhèn)IT培訓認為如果外接了cache或squid服務器要求進行web加速的話,就需要在htttpd.conf里進行設置,當然前提是在安裝apache的時候要激活mod_cache的模塊。
Session 和 Cookie 有什么關系
Cookie 也是由于 HTTP 無狀態(tài)的特點而產生的技術。也被用于保存訪問者的身份標示和一些數(shù)據。每次客戶端發(fā)起 HTTP 請求時,會將 Cookie 數(shù)據加到 HTTP header 中,提交給服務端。這樣服務端就可以根據 Cookie 的內容知道訪問者的信息了。 可以說,Session 和 Cookie 做著相似的事情,只是 Session 是將數(shù)據保存在服務端,通過客戶端提交來的 session_id 來獲取對應的數(shù)據;而 Cookie 是將數(shù)據保存在客戶端,每次發(fā)起請求時將數(shù)據提交給服務端的。
上面提到,session_id 可以通過 URL 或 cookie 來傳遞,由于 URL 的方式比 cookie 的方式更加不安全且使用不方便,所以一般是采用 cookie 來傳遞 session_id。
服務端生成 session_id,通過 HTTP 報文發(fā)送給客戶端(比如瀏覽器),客戶端收到后按指示創(chuàng)建保存著 session_id 的 cookie。cookie 是以 key/value 形式保存的,看上去大概就這個樣子的:PHPSESSID=e4tqo2ajfbqqia9prm8t83b1f2。在 PHP 中,保存 session_id 的 cookie 名稱默認叫作 PHPSESSID,這個名稱可以通過 php.ini 中 session.name 來修改,也可以通過函數(shù) session_name() 來修改。
為什么不推薦使用 PHP 自帶的 files 型 Session 處理器
在 PHP 中,默認的 Session 處理器是 files,處理器可以用戶自己實現(xiàn)(參見:自定義會話管理器)。我知道的成熟的 Session 處理器還有很多:Redis、Memcached、MongoDB……
為什么不推薦使用 PHP 自帶的 files 類型處理器,PHP 官方手冊中給出過這樣一段 Note:
無論是通過調用函數(shù) session_start() 手動開啟會話, 還是使用配置項 session.auto_start 自動開啟會話, 對于基于文件的會話數(shù)據保存(PHP 的默認行為)而言, 在會話開始的時候都會給會話數(shù)據文件加鎖, 直到 PHP 腳本執(zhí)行完畢或者顯式調用 session_write_close() 來保存會話數(shù)據。 在此期間,其他腳本不可以訪問同一個會話數(shù)據文件。
上述引用參見:Session 的基本用法
為了證明這段話,我們創(chuàng)建一下 2 個文件: 文件:session1.php
?php
session_start();
sleep(5);
var_dump($_SESSION);
?
文件:session2.php
?php
session_start();
var_dump($_SESSION);
?
在同一個瀏覽器中,先訪問 ,然后在當前瀏覽器新的標簽頁立刻訪問 。實驗發(fā)現(xiàn),session1.php 等了 5 秒鐘才有輸出,而 session2.php 也等到了將近 5 秒才有輸出。而單獨訪問 session2.php 是秒開的。在一個瀏覽器中訪問 session1.php,然后立刻在另外一個瀏覽器中訪問 session2.php。結果是 session1.php 等待 5 秒鐘有輸出,而 session2.php 是秒開的。
分析一下造成這個現(xiàn)象的原因:上面例子中,默認使用 Cookie 來傳遞 session_id,而且 Cookie 的作用域是相同。這樣,在同一個瀏覽器中訪問這 2 個地址,提交給服務器的 session_id 就是相同的(這樣才能標記訪問者,這是我們期望的效果)。當訪問 session1.php 時,PHP 根據提交的 session_id,在服務器保存 Session 文件的路徑(默認為 /tmp,通過 php.ini 中的 session.save_path 或者函數(shù) session_save_path() 來修改)中找到了對應的 Session 文件,并對其加鎖。如果不顯式調用 session_write_close(),那么直到當前 PHP 腳本執(zhí)行完畢才會釋放文件鎖。如果在腳本中有比較耗時的操作(比如例子中的 sleep(5)),那么另一個持有相同 session_id 的請求由于文件被鎖,所以只能被迫等待,于是就發(fā)生了請求阻塞的情況。
既然如此,在使用完 Session 后,立刻顯示調用 session_write_close() 是不是就解決問題了哩?比如上面例子中,在 sleep(5) 前面調用 session_write_close()。
確實,這樣 session2.php 就不會被 session1.php 所阻塞。但是,顯示調用了 session_write_close() 就意味著將數(shù)據寫到文件中并結束當前會話。那么,在后面代碼中要使用 Session 時,必須重新調用 session_start()。
例如:
?php
session_start();
$_SESSION['name'] = 'Jing';
var_dump($_SESSION);
session_write_close();
sleep(5);
session_start();
$_SESSION['name'] = 'Mr.Jing';
var_dump($_SESSION);
?
官方給出的方案:
對于大量使用 Ajax 或者并發(fā)請求的網站而言,這可能是一個嚴重的問題。 解決這個問題最簡單的做法是如果修改了會話中的變量, 那么應該盡快調用 session_write_close() 來保存會話數(shù)據并釋放文件鎖。 還有一種選擇就是使用支持并發(fā)操作的會話保存管理器來替代文件會話保存管理器。
我推薦的方式是使用 Redis 作為 Session 的處理器。
拓展閱讀:
為什么不能用 memcached 存儲 Session
如何使用 Redis 作為 PHP Session handler
Session 數(shù)據是什么時候被刪除的
這是一道經常被面試官問起的問題。
先看看官方手冊中的說明:
session.gc_maxlifetime 指定過了多少秒之后數(shù)據就會被視為"垃圾"并被清除。 垃圾搜集可能會在 session 啟動的時候開始( 取決于 session.gc_probability 和 session.gc_divisor)。 session.gc_probability 與 session.gc_divisor 合起來用來管理 gc(garbage collection 垃圾回收)進程啟動的概率。此概率用 gc_probability/gc_divisor 計算得來。例如 1/100 意味著在每個請求中有 1% 的概率啟動 gc 進程。session.gc_probability 默認為 1,session.gc_divisor 默認為 100。
繼續(xù)用我上面那個不太恰當?shù)谋确桨桑喝绻覀儼盐锲贩旁诔械膬ξ锵渲卸蝗∽撸^了很久(比如一個月),那么保安就要清理這些儲物箱中的物品了。當然并不是超過期限了保安就一定會來清理,也許他懶,又或者他壓根就沒有想起來這件事情。
再看看兩段手冊的引用:
如果使用默認的基于文件的會話處理器,則文件系統(tǒng)必須保持跟蹤訪問時間(atime)。Windows FAT 文件系統(tǒng)不行,因此如果必須使用 FAT 文件系統(tǒng)或者其他不能跟蹤 atime 的文件系統(tǒng),那就不得不想別的辦法來處理會話數(shù)據的垃圾回收。自 PHP 4.2.3 起用 mtime(修改時間)來代替了 atime。因此對于不能跟蹤 atime 的文件系統(tǒng)也沒問題了。
GC 的運行時機并不是精準的,帶有一定的或然性,所以這個設置項并不能確保舊的會話數(shù)據被刪除。某些會話存儲處理模塊不使用此設置項。
對于這種刪除機制,我是存疑的。
比如 gc_probability/gc_divisor 設置得比較大,或者網站的請求量比較大,那么 GC 進程啟動就會比較頻繁。
還有,GC 進程啟動后都需要遍歷 Session 文件列表,對比文件的修改時間和服務端的當前時間,判斷文件是否過期而決定是否刪除文件。
這也是我覺得不應該使用 PHP 自帶的 files 型 Session 處理器的原因。而 Redis 或 Memcached 天生就支持 key/value 過期機制的,用于作為會話處理器很合適?;蛘咦约簩崿F(xiàn)一個基于文件的處理器,當根據 session_id 獲取對應的單個 Session 文件時判斷文件是否過期。
為什么重啟瀏覽器后 Session 數(shù)據就取不到了
session.cookie_lifetime 以秒數(shù)指定了發(fā)送到瀏覽器的 cookie 的生命周期。值為 0 表示"直到關閉瀏覽器"。默認為 0。
其實,并不是 Session 數(shù)據被刪除(也有可能是,概率比較小,參見上一節(jié))。只是關閉瀏覽器時,保存 session_id 的 Cookie 沒有了。也就是你弄丟了打開超市儲物箱的鑰匙(session_id)。
同理,瀏覽器 Cookie 被手動清除或者其他軟件清除也會造成這個結果。
為什么瀏覽器開著,我很久沒有操作就被登出了
這個是稱為“防呆”,為了保護用戶賬戶安全的。
這個小節(jié)放進來,是因為這個功能的實現(xiàn)可能和 Session 的刪除機制有關(之所以說是可能,是因為這個功能不一定要借住 Session 實現(xiàn),用 Cookie 也同樣可以實現(xiàn))。 說簡單一點,就是長時間沒有操作,服務端的 Session 文件過期被刪除了。
一個有意思的事情
在我試驗的過程中,發(fā)現(xiàn)了小有意思的事情:我把 GC 啟動的概率設置為 100%。如果只有一個訪問者請求,該訪問者即使過了很久(超過了過期時間)后才發(fā)起第二次請求,那么 Session 數(shù)據也還是存在的('session.save_path' 目錄下面的 Session 文件存在)。是的,明明就超過了過期時間,卻沒有被 GC 刪除。這時,我用另外一個瀏覽器訪問時(相對于另一個訪問者),這次請求生成了新的 Session 文件,而上一個瀏覽器請求生成的那個 Session 文件終于沒有了(之前那個 Session 文件在 'session.save_path' 目錄下面的消失了)。
還有,發(fā)現(xiàn) Session 文件被刪除后,再次請求,還是會生成和之前文件名相同的 Session 文件(因為瀏覽器并沒有關閉,再次請求發(fā)送的 session_id 是相同的,所以重新生成的 Session 文件的文件名還是一樣的)。但是,我不理解的是:這個重新出現(xiàn)的文件的創(chuàng)建時間竟然是第一次的那個創(chuàng)建時間,難道它是從回收站中回來的?(確實,我做這個試驗時是在 window 下進行的)
我猜測的原因是這樣:當啟動會話后,PHP 根據 session_id 找到并打開了對應的 Session 文件,然后才啟動 GC 進程。GC 進程就只檢查除了當前這個 Session 文件外的其他文件,發(fā)現(xiàn)過期的就干掉。所有,即使當前這個 Session 文件已經過期了,GC 也沒有刪除它。
我認為這個不合理的。
由于發(fā)生這種情況影響也不大(畢竟線上請求很多,當前請求的過期文件被其他請求喚起的 GC 干掉的可能性是比較大的) + 我沒有信心去看 PHP 源代碼 + 我并不在線上使用 PHP 自帶的 files 型 Session 處理器。所以,這個問題我就沒有深入研究了。請諒解。
?php
// 過期時間設置為 30 秒
ini_set('session.gc_maxlifetime', '30');
// GC 啟動概率設置為 100%
ini_set('session.gc_probability', '100');
ini_set('session.gc_divisor', '100');
session_start();
$_SESSION['name'] = 'Jing';
var_dump($_SESSION);
?