一、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