一、CDN緩存原理和介紹
1、各地部署多套靜態存儲服務,本質上是空間成本換時間
2、CDN是域名和真實服務器中間的一個環節,添加cdn節點后,用戶訪問時,自動選擇最近的節點內容,不存在再請求原始服務器
3、CDN本質上是一種文件分發類系統,適合存儲更新很少的靜態內容,文件更新慢
注:cdn文件同步有兩種方式
第一種:文件更新之后,由原始服務器將內容推送到cdn上
第二種:為cdn設置過期時間,到期之后,重新請求原始服務器獲取最新數據
一般中小型公司,都是采用的免費的云cdn,比如阿里云的cdn分發系統、百度云的內容分發網絡cdn等。
對于超大型公司來說,可能會采用自己搭建cdn系統的方式,但成本較高。
二、數據文件緩存方案
原理:將更新頻率極低,且讀取幾率高的數據緩存為文件,獲取時,不再查詢數據庫,而是直接讀和解析緩存文件內容。
代碼實現:
1、首先查詢一遍數據庫,并將查詢到的數據生成 .json靜態文件
public function BannerToJson(){//1.我需要從數據庫里提取到對應的焦點圖的數據,
$BannerModel = new BannerBiz();
$json = $BannerModel->GetBannerJson(7);
//2.把數據進行整理,并生成為json格式,
$RewriteModel = new RewriteBiz();
$result = $RewriteModel->ToJson($json);
if ($result){echo "焦點圖生成成功";
}else{echo "焦點圖生成失敗";
}
}
2、之后,前臺進行請求的時候,直接ajax請求之前生成好的json文件,就不需要再查詢數據庫了(缺點:實時性差)
//首頁的輪播圖 $.ajax({url: "/json/banner.json" , type: "get", dataType: "json", async: false, success: function(json){if(json != null){for(var i=0;i<json.length;i++){$('.mainpage-slideshow-top .banner').append('<a href="'+json[i].url+'"><img src="'+json[i].pic+'" </a>'); }}}, error: function(){console.log( "AJAX fail"); }}); //需要jquery.slideshow.js,可更改輪播間隔和主題顏色 $(".mainpage-slideshow-top").slideShow({color: "#f10823"});
總結:此方案類似于redis緩存或者memcache緩存,都是先把數據緩存到其他地方,避免頻繁查詢數據庫
缺點:這種方案都有一種缺點,就是實時性比較差,需要我們寫定時任務或者其他方式去定時更新緩存數據文件。這種方式比較適合新聞類網站,信息更新不是特別頻繁。
三、全頁面靜態化
全頁面靜態化大致分為兩種,一種是用類似smarty模板引擎實現,另一種則是是用ob實現,這里介紹的是類似smarty緩存的方式實現,但是推薦使用ob方式來實現頁面靜態化。
注:ob實現頁面靜態化?
原理:https://blog.csdn.net/guoshaoqing001/article/details/46673147
代碼實現:https://blog.csdn.net/m_nanle_xiaobudiu/article/details/79267703
數據文件緩存與全頁面靜態化對比:
數據緩存方案:
只是先將數據生成了靜態文件,然后前臺用ajax請求數據緩存文件,得到數據,展示給用戶。
而全頁面靜態化:
則是直接將從數據庫查詢到的數據和前端頁面進行結合,生成靜態文件,存儲在硬盤,用戶訪問時,直接請求生成的全靜態頁面,既沒有數據庫查詢了,又沒有了ajax請求了,直接將頁面展示給用戶即可。
代碼實現方式:
常見于cms(內容管理系統),使用前后端分離的思想,如smarty,把頁面共用區域做成模板,并留下變量區域,后臺修改內容時,把變量替換入模板,并生成html。用戶訪問時,直接顯示html頁面。
全頁面靜態化:
優點:
有利于搜索引擎優化(seo),加快收錄速度。
減輕服務器負擔,減少數據庫請求和運算量。
加快頁面打開速度,便于進行cdn分發。
由于是靜態文件,防止了漏洞和入侵。
非常適合文章類網站。
代碼實現:
控制器部分:
/** * 全頁面靜態化代碼實現 */ public function ChannelToHtml(){//1.從數據庫取出需要的數據【取數據就是普通的增刪改查,不必關注】 $channel_ids = array(1,2,3,4); $ChannelBiz = new ChannelBiz(); $channel_data = array(); foreach ($channel_ids as $channel_id) {//根據channel_id循環取出相應數據,并將四組數據放到同一個數組中 array_push($channel_data , $ChannelBiz->GetChannelContent($channel_id)); }//2.將從數據庫取出的合并后的數據替換到html模板的相應位置 $RewriteBiz = new RewriteBiz(); $res = $RewriteBiz -> ToHtml('channel',$channel_data); if ($res) {echo '欄目生成成功'; } else {echo '欄目生成失敗'; }}
public function ToHtml($type , $data){if ('channel' == $type){//1.通過數組來取到對應的四個模塊的html, $html_part = $this->GetChannelPart($data); //2.取到整頁面的html模板, $html_template = file_get_contents(SITE_PATH.'/public/template/channel.html'); //3.將四個欄目替換到模板的對應位置, $res_html = str_replace('<{channel_list}>' ,$html_part,$html_template); // 4.將合成后的html生成為靜態文件,【fopen、fwrite、fclose這一套 相當于 file_put_contens,作用相似】 $file = fopen(SITE_PATH.'/public/channel/channel.html','w'); $res = fwrite($file,$res_html); fclose($file); if ($res) {return true; } else {return false; }} }
public function GetChannelPart($data ,$i = 1){$html = file_get_contents(SITE_PATH.'/public/template/channel_part.html');
$res_html = '';
foreach ($data as $channel_data) {$part_html = $html;
$part_sub_channel = $part_goods = $part_goods_foot = $part_brand = '';
$part_html = str_replace('<{i}>',$i,$part_html);
$part_html = str_replace('<{channel_title}>',$channel_data['Info']['title'],$part_html);
//子欄目部分,
foreach ($channel_data['SubChannel'] as $sub_channel) {$part_sub_channel .= "<li><a href=\"".$sub_channel['url']."\">".$sub_channel['title']."</a></li>";
}$part_html = str_replace('<{channel_link}>',$part_sub_channel,$part_html);
//商品部分,
$part_html = str_replace('<{main_goods}>','<a href="'.$channel_data['Goods'][1][0]['url'].'"><img src="'.$channel_data['Goods'][1][0]['pic_url'].'"></a>',$part_html);
//小商品部分,
foreach ($channel_data['Goods'][2] as $good) {$part_goods .= '<li><a href="'.$good['url'].'"><p>'.$good['title'].'</p><p>'.$good['subtitle'].'</p><img src="'.$good['pic_url'].'"></a></li>';
}$part_html = str_replace('<{four_goods}>',$part_goods,$part_html);
//小商品部分,
foreach ($channel_data['Goods'][3] as $good) {$part_goods_foot .= '<li><a href="'.$good['url'].'"><p>'.$good['title'].'</p><p>'.$good['subtitle'].'</p><img src="'.$good['pic_url'].'"></a></li>';
}$part_html = str_replace('<{foot_goods}>',$part_goods_foot,$part_html);
//品牌,,
foreach ($channel_data['Brand'] as $good) {$part_brand .= '<li><a href="'.$good['url'].'"><img src="'.$good['pic_url'].'"></a></li>';
}$part_html = str_replace('<{brands}>',$part_brand,$part_html);
$res_html .= $part_html;
$i++;
}return $res_html;
}
html模板:
channel.html 以及 channel_part.html
<!DOCTYPE html> <html> <head> <title>京西頻道頁面</title> <meta charset="utf-8"> <link rel="stylesheet" type="text/css" href="/static/css/reset.css"> <link rel="stylesheet" type="text/css" href="/static/css/common.css"> <link rel="stylesheet" type="text/css" href="/static/css/main.css"> <link rel="icon" href="/static/img/icon.ico"> <script type="text/javascript" src="/static/js/jquery.js"></script> <script type="text/javascript" src="/static/js/jquery.slideshow.js"></script> <script type="text/javascript" src="/static/js/jquery.smimgslide.js"></script> <script type="text/javascript" src="/static/js/jquery.countdown.js"></script> <script type="text/javascript" src="/static/js/main.js"></script> </head> <body> <div class="header"> <div class="header-nav common-container"> <ul class="header-nav-list"> <li><h3><a href="#">秒殺</a></h3></li> <li><h3><a href="#">優惠券</a></h3></li> <li><h3><a href="#">閃購</a></h3></li> <li><h3><a href="#">拍賣</a></h3></li> <li><h3><a href="#">服裝城</a></h3></li> <li><h3><a href="#">京西超市</a></h3></li> <li><h3><a href="#">生鮮</a></h3></li> <li><h3><a href="#">全球購</a></h3></li> <li><h3><a href="#">京西金融</a></h3></li> </ul> </div> </div> <div class="lovelife"> <div class="common-container clearfloat lovelife-box"> <div class="common-title"> <i></i> <h2>愛生活</h2> <i></i> </div> <ul class="lovelife-list clearfloat"> <{channel_list}> </ul> </div> </div> <!-- footer start --> <div class="footer"> <div class="footer-slogans"> <ul> <li class="footer-slogans-item1"><i></i> <h3>品類齊全,輕松購物</h3></li> <li class="footer-slogans-item2"><i></i> <h3>多倉直發,極速配送</h3></li> <li class="footer-slogans-item3"><i></i> <h3>正品行貨,精致服務</h3></li> <li class="footer-slogans-item4"><i></i> <h3>天天低價,暢選無憂</h3></li> </ul> </div> <div class="common-container clearfloat"> <div class="footer-sevice clearfloat"> <table class="footer-sevice-table"> <thead> <tr> <th>購物指南</th> <th>配送方式</th> <th>支付方式</th> <th>售后服務</th> <th>特色服務</th> </tr> </thead> <tbody> <tr> <td><a href="#">購物流程</a></td> <td><a href="#">上門自提</a></td> <td><a href="#">貨到付款</a></td> <td><a href="#">售后政策</a></td> <td><a href="#">奪寶島</a></td> </tr> <tr> <td><a href="#">會員介紹</a></td> <td><a href="#">211限時達</a></td> <td><a href="#">在線支付</a></td> <td><a href="#">價格保護</a></td> <td><a href="#">DIY裝機</a></td> </tr> <tr> <td><a href="#">生活旅行</a></td> <td><a href="#">配送服務查詢</a></td> <td><a href="#">分期付款</a></td> <td><a href="#">退款說明</a></td> <td><a href="#">延保服務</a></td> </tr> <tr> <td><a href="#">常見問題</a></td> <td><a href="#">配送費收取標準</a></td> <td><a href="#">郵局匯款</a></td> <td><a href="#">返修/退換貨</a></td> <td><a href="#">京西E卡</a></td> </tr> <tr> <td><a href="#">大家電</a></td> <td><a href="#">海外配送</a></td> <td><a href="#">公司轉賬</a></td> <td><a href="#">取消訂單</a></td> <td><a href="#">京西通信</a></td> </tr> <tr> <td><a href="#">聯系客服</a></td> <td></td> <td></td> <td></td> <td><a href="#">京西JD+</a></td> </tr> </tbody> </table> <div class="footer-sevice-info"> <h5>京西自營覆蓋區縣</h5> <p>京西已向全國2654個區縣提供自營配送服務,支持貨到付款、POS機刷卡和售后上門服務。</p> <p><a href="#">查看詳情 ></a></p> </div> </div> <div class="footer-lists"> <ul class="footer-lists-links"> <li><a href="#">關于我們</a></li> <li>|</li> <li><a href="#">聯系我們</a></li> <li>|</li> <li><a href="#">商家入駐</a></li> <li>|</li> <li><a href="#">營銷中心</a></li> <li>|</li> <li><a href="#">手機京西</a></li> <li>|</li> <li><a href="#">友情鏈接</a></li> <li>|</li> <li><a href="#">銷售聯盟</a></li> <li>|</li> <li><a href="#">京西社區</a></li> <li>|</li> <li><a href="#">風險監測</a></li> <li>|</li> <li><a href="#">京西公益</a></li> <li>|</li> <li><a href="#">English Site</a></li> <li>|</li> <li><a href="#">Contact Us</a></li> </ul> <br> <ul class="footer-lists-line1"> <li><a href="#">京公網安備 11000002000088號</a></li> <li>|</li> <li>京ICP證070359號</li> <li>|</li> <li><a href="#">互聯網藥品信息服務資格證編號(京)-經營性-2014-0008</a></li> <li>|</li> <li>新出發京零 字第大120007號</li> </ul> <br> <ul class="footer-lists-line2"> <li>互聯網出版許可證編號新出網證(京)字150號</li> <li>|</li> <li><a href="#">出版物經營許可證</a></li> <li>|</li> <li><a href="#">網絡文化經營許可證京網文[2014]2148-348號</a></li> <li>|</li> <li>違法和不良信息舉報電話:4006561155</li> </ul> <br> <ul class="footer-lists-line3"> <li>Copyright © 2004 - 2016 京西JD.com 版權所有</li> <li>|</li> <li>消費者維權熱線:4006067733 <a href="#">經營執照</a></li> </ul> <br> <ul class="footer-lists-line4"> <li>京西旗下網站:<a href="#">京西錢包</a></li> <li>|</li> <li><a href="#">京西云</a></li> </ul> <br> <ul class="footer-lists-icons"> <li class="footer-lists-icons-item1"><a href="#"></a></li> <li class="footer-lists-icons-item2"><a href="#"></a></li> <li class="footer-lists-icons-item3"><a href="#"></a></li> <li class="footer-lists-icons-item4"><a href="#"></a></li> <li class="footer-lists-icons-item5"><a href="#"></a></li> <li class="footer-lists-icons-item6"><a href="#"></a></li> </ul> </div> </div> </div> <!-- footer end --> </body> </html>
<li class="lovelife-list-item<{i}> lovelife-list-col2 sidebarpointer" > <div class="lovelife-list-title"> <h3><{channel_title}> </h3> <ul> <{channel_link}> </ul> </div> <div class="lovelife-list-content"> <div class="lovelife-list-content-box"> <div class="lovelife-list-content-leimg"> <{main_goods}> </div> <ul class="lovelife-list-content-riimg"> <{four_goods}> </ul> <ul class="lovelife-list-content-mdimg"> <{foot_goods}> </ul> </div> </div> <div class="lovelife-list-smimg"> <span class="lovelife-list-smimg-leftarrow"><</span> <span class="lovelife-list-smimg-rightarrow">></span> <div class="lovelife-list-smimg-box"> <ul> <{brands}> </ul> </div> </div> </li>
到此,類似smarty實現全頁面靜態化的工作就完成了。
四、數據分塊加載——BigPipe 技術【類似facebook】
原理:分塊加載,加載完一塊,就先把頁面數據刷給用戶,再加載下面的,直到加載完畢
實現:https://blog.csdn.net/m_nanle_xiaobudiu/article/details/80976332
五、 Memcache 緩存的應用
1、memcache安裝及在項目中的使用?
https://blog.csdn.net/m_nanle_xiaobudiu/article/details/79279261
注:常用操作命令:http://www.runoob.com/memcached/php-connect-memcached.html
2、Memcache 和 Memcached的區別:
可以將memcached看做是memcache的升級版,memcache支持面向對象和面向過程兩種寫法,而memcached只支持面向對象的寫法。
3、Memcache 和 Redis 的使用場景和性能的對比
實際上,這里并不推薦使用memcache,不僅是因為memcache沒有認證和安全機制,而且不支持持久化,數據一旦丟失,或者memcache宕機,就將面臨崩潰。同樣是做緩存,更推薦使用redis。當然,具體還要根據業務場景做規劃選擇。
注:想要詳細了解 memcache 和 redis的區別:https://www.cnblogs.com/Hondsome/p/5962144.html
六、集中式服務器——session共享問題
更改php.ini
默認php的session是存儲在文件中的,我們需要更改成存儲到memcache或者redis中
session.save_handler = "memcached"? ?#將session存儲到memcache
session.save_path = "tcp://127.0.0.1:11211"? ?#填寫memcache訪問路徑,如果是php7以上版本,“tcp://?”可以省略
注:
如果只想某一個php文件中的session存儲在緩存中,則可以在該文件中單獨定義上面兩個參數。
七、Nosql 之 Redis 內存數據庫
1、簡介:
Redis是完全開源免費的,遵守BSD協議,是一個高性能的key-value數據庫。
Redis擁有更多的數據結構,并支持更豐富的數據操作。
Redis支持數據持久化和數據恢復。
Redis的所有操作都是原子性的(相當于事務)。
簡單的key-value存儲,性能極高。
服務端支持AUTH密碼驗證。
手冊下載:https://download.csdn.net/download/m_nanle_xiaobudiu/10532352
2、常用命令
http://www.runoob.com/redis/redis-commands.html
3、用redis實現秒殺功能
https://blog.csdn.net/m_nanle_xiaobudiu/article/details/80479666
4、用redis實現數據庫緩存功能
https://blog.csdn.net/m_nanle_xiaobudiu/article/details/79280419
5、運用redis緩存時,對于類型的選擇
5.1、單一的key-value,自不必說,用string類型
5.2、如果是運用在消息隊列,則選擇list類型
5.3、如果是類似商品屬性子屬性,則選擇hash類型
5.4、如果用于集合對比運算,比如南北差異,則使用set類型
5.5、如果用于顯示排行榜,比如收藏榜,點擊榜,則使用zset類型
6、Redis 持久化方案
兩種方式:
RDB:指定的時間間隔內保存數據快照
AOF:先把命令追加到操作日志的尾部,保存所有的歷史操作
詳見:https://blog.csdn.net/m_nanle_xiaobudiu/article/details/81001504
7、如何合理使用Redis
(1)防止內存占滿
設置默認超時時間,避免key一直不釋放。
不存放大文件,一般存儲redis緩存時,一個鍵值對最好不要超過500字節。
不存儲不常用數據,只存儲高頻數據(熱數據)。
(2)提高使用效率
慎用正則處理。
合理使用不同的數據結構類型。
慎用批量操作Hash、Set 等。
8、六臺機器搭建RedisCluster分布式集群
鏈接:https://blog.csdn.net/m_nanle_xiaobudiu/article/details/81004557