使用redis实现页面缓存
来源:互联网 发布:奶奶抱走红网络 编辑:程序博客网 时间:2024/06/07 09:27
本文是<<redis in action>>一书 第二章的读书笔记
我们要缓存的就是形式如下面的url
http://test.com/shwoItem?item=itemX设计方案
第一个域,是zset类型的------key是viewed:userSessionid存放的是商品id与用户查看此商品时的timestamp
第二个域,是zset类型的------可以是viewed:
member是商品id(全局范围内),score是商品被用户(全局范围内)浏览的次数(是负数)
第三个域,是hash类型的------key是item:itemId
存放的是商品的信息
用户查看了某件商品
public void viewItem(Jedis conn, String token, String user, String item) {long timestamp = System.currentTimeMillis() / 1000;if (item != null) { //用户user在某时浏览了某件商品conn.zadd("viewed:" + token, timestamp, item);//只记录用户最近查看的25件商品conn.zremrangeByRank("viewed:" + token, 0, -26);//有序set里 score的越小排名越靠前conn.zincrby("viewed:", -1, item); //-1还是1?}}
试着缓存这个页面
首先我们要判断,某个url是否能缓存/** * 如果request 不符合规范 就不缓存 返回false * 如果商品还没有被访问过 自然不能缓存 返回false * 如果商品被访问过 但是访问的排名在10000之后 也就不缓存了 返回false * 如果商品被访问过 且访问的排名在10000之内 就说明可以缓存 返回true * * @param conn * @param request * @return */public boolean canCache(Jedis conn, String request) {//从类似http://test.com/shwoItem?item=itemX//这样的字符串中获得paramter 代码就不赘述了Map<String, String> params = getParams(request);if (params == null) return false;//获得itemX这个信息String itemId = extractItemId(params);//params.containsKey("_") 这个条件只是示例//用户可以加上自己的判别条件if (itemId == null || params.containsKey("_")) {return false;}// viewed:这个有序集里存放的是 商品的访问次数Long rank = conn.zrank("viewed:", itemId);// 查看这个商品的访问量是否在前10000内//如果rank==null 说明商品还没有被访问过return rank != null && rank < 10000;}
实现缓存request
public String cacheRequest(Jedis conn, String request, Callback callback) {if (!canCache(conn, request)) {return callback != null ? callback.call(request) : null;}String pageKey = "cache:" + hashRequest(request);//这个只是示例 真实的情况 应该是复杂的业务逻辑产生最后的反馈页面String content = conn.get(pageKey); if (content == null && callback != null) {content = callback.call(request);//我们可以认为这个content就是html//我们将要显示的数据缓存5分钟conn.setex(pageKey, 300, content);}return content;}传入的callback如下:
Callback callback = new Callback() {public String call(String request) {return "content for " + request;}};
我们看看测试代码
package redisinaction;import org.junit.BeforeClass;import org.junit.Test;import redis.clients.jedis.Jedis;import redisinaction.Chapter02.Callback;/** * This class is used for ... * @author dlf(460795365@qq.com) * @version 1.0, 2016年10月18日 下午9:34:27 */public class Chapter02Test {static Jedis conn = null;static Chapter02 ch2=null;@BeforeClass public static void initConn(){System.out.println("test before");ch2=new Chapter02();conn = new Jedis("10.150.0.80");conn.auth("dlf123123");} @Testpublic void testCacheRequest() {Callback callback = new Callback() {public String call(String request) {return "content for " + request;}};//必须先viewItem 否则不管调用几次cacheRequest 都不能缓存//为什么? 自己想ch2.viewItem(conn, "dlf_session_id", "dlf", "itemX");String url = "http://test.com/?item=itemX";String result = ch2.cacheRequest(conn, url, callback);System.out.println( result);String result3 = ch2.cacheRequest(conn, url, null);System.out.println(result3);String result4 = ch2.cacheRequest(conn, url, null);System.out.println(result4);}}
全局范围内被用户查看最多的n件产品(和上一章那个文章排序差不多)
private static final int ARTICLES_PER_PAGE = 25; public List<Map<String,String>> getMostPopulate(Jedis conn, int page) { int start = (page - 1) * ARTICLES_PER_PAGE; int end = start + ARTICLES_PER_PAGE - 1; Set<String> ids = conn.zrevrange("viewed:", start, end); List<Map<String,String>> items = new ArrayList<Map<String,String>>(); for (String id : ids){ Map<String,String> itemData = conn.hgetAll(id); itemData.put("id", id); items.add(itemData); } return items; }
在viewItem里,我们已经记录了所有商品的浏览次数(负数)
conn.zincrby("viewed:", -1, item);
那么经过n天后,这个viewed里的数据项就很多了,而且其实也没有必要一直保存着所有商品的浏览次数
所以
public class RescaleViewedThread implements Runnable{private Jedis conn;private boolean quit;public RescaleViewedThread(int limit) {conn = new Jedis("10.150.0.80"); conn.auth("dlf123123");}public void shutDown(){quit=true;}@Overridepublic void run() {while (!quit) {try {//移除排名20000之后的商品浏览信息conn.zremrangeByRank("viewed:", 0, -20001);//将所有商品的浏览数量降低一半conn.zinterstore("viewed","viewed:0.5");Thread.sleep(300);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}系统启动后就,一直运行这个线程。
那么怎么做呢?怎么集成到我的项目里呢?我的项目是使用struts2开发的。
哥哥,您不知道有个东西叫拦截器么?interceptor?
看这个:http://www.2cto.com/kf/201506/408009.html
这个是springmvc的?struts怎么用?
笨死!
在struts2的拦截器里获得request和response你不会么?
0 0
- 使用redis实现页面缓存
- redis实现web页面缓存
- 使用spring+redis实现缓存
- Django使用redis实现缓存
- 使用EhCache实现页面缓存
- Magento 2 页面缓存和默认缓存中使用Redis
- 使用Spring Data +Redis实现缓存
- Spring Boot使用redis实现数据缓存
- SpringBoot中使用Redis实现缓存
- javaEE 导航栏使用redis缓存实现
- nginx+redis 实现 jsp页面缓存,提升系统吞吐率
- WP_使用_FastCGI_Cache_实现高效页面缓存
- redis实现缓存
- redis实现缓存
- spring + redis实现缓存
- mybatis缓存 redis实现
- MyBatis+Redis缓存实现
- REDIS实现数据缓存
- java--Struts2的There is no Action mapped for namespace错误
- Sicily1133: SPAM (电子邮箱匹配)
- PRVF-0002 : 无法检索本地节点名
- Laravel 5.2 自增id问题
- 反转一个链表
- 使用redis实现页面缓存
- 基于git+rsync的代码--备份/上线/回滚--脚本一例
- 在Win10 的bash下安装TensorFlow
- C语言问答
- 新标准日本语中级下(第6单元)笔记
- 内存
- 基于SD卡和PC的ARM常用镜像烧录方式——通过Exynos4412测试
- Android温习之路:Day8java基础8
- Dom事件的基础及应用