需求
1.实现任意数据行的可以设计不同的延迟周期进行刷新或者同步任务
2.最热的2000个商品缓存
自动延迟调度
加入调度列表
/** * 将需要主动更新的的数据加入自动调度列表 * @param conn * @param row_id * @param delay */ public static void scheduleRowCache(Jedis conn,String row_id,int delay){ //记录此id周期多少秒执行一次 刷新 conn.zadd("delay:",delay,row_id); //加入定时执行列表 并设置立即执行 conn.zadd("schedule:",System.currentTimeMillis(),row_id); }
调度方法
public static void run(Jedis conn){ new Thread(new Runnable() { @Override public void run() { while (true) { //获取需要立即执行的列表 Setids = conn.zrangeByScore("schedule:", 0, System.currentTimeMillis()); //没有则释放时间片 同时暂停500毫秒 if (ids == null || ids.size() <= 0) { Thread.yield(); try { Thread.sleep(500L); } catch (InterruptedException e) { e.printStackTrace(); } } for (String id : ids) { System.out.println(id + "执行了数据刷新"); //获得此数据延迟时间 Double delay = conn.zscore("delay:", id); //重新加入延迟队列 //加入定时执行列表 并设置立即执行 conn.zadd("schedule:", System.currentTimeMillis() + (delay * 1000), id); } } } }).start();; }
测试
public static final void main(String[] args) throws Exception { Jedis conn = new Jedis("127.0.0.1", 6379); conn.select(15); //5秒刷新一次 scheduleRowCache(conn,"1",5); run(conn); Thread.sleep(1000000); }
最热商品缓存
访问商品
/** * 更新rank * @param conn * @param productId * @return * @throws InterruptedException */ public static String viewProduct(Jedis conn,String productId) throws InterruptedException { //更新评分 conn.zincrby("viewed:",-1,productId); //获得排名 double rank= conn.zrank("viewed:",productId); String html=null; //如果<=2000表示走缓存 if(rank<=2000){ //先查缓存 html= conn.get("product:"+productId); if(html==null){ html=select(productId); conn.set("product:"+productId,html); } }else{ html =select(productId); } return html; }
/** * 模拟db 和生成html * @return * @throws InterruptedException */ public static String select(String productId) throws InterruptedException { Thread.sleep(2000); return String.format("我是商品%s的商品详情html",productId); }
定时任务清除非热点数据
/** * 此方法应该定时任务5秒调用一次 * @param conn */ public static void clearCache(Jedis conn){ conn.zremrangeByRank("viewed:",0,-2001); //将所有商品的浏览数量降低一半 未测试通过,,,不造咋减半的 书上py是这样写 conn.zinterstore("viewed:","{'viewed:':0.5"); }
测试
public static void main(String[] args) throws Exception { Jedis conn = new Jedis("127.0.0.1", 6379); conn.select(15); viewProduct(conn,"3"); viewProduct(conn,"3"); viewProduct(conn,"3"); viewProduct(conn,"3"); viewProduct(conn,"3"); viewProduct(conn,"3"); //清空2000排名以外的 同时重置2000以内的排名 conn.zscore("viewed:","3") clearCache(conn); Thread.sleep(1000000); }