redisによるページキャッシュの実装
本文は<>一書第二章の読書ノート
キャッシュするのは次のurlのような形ですhttp://test.com/shwoItem?item=itemX
保管されているのは、商品idとユーザーがこの商品を表示するときのtimestampです.
2番目のドメインは、zsetタイプの------viewedであってもよい.
メンバーは商品id(グローバル範囲内)、scoreは商品がユーザ(グローバル範囲内)に閲覧された回数(負数)である
3番目のドメイン、hashタイプの------keyはitem:itemIdです
商品情報をお預かりしております
グローバル範囲でユーザーに最も多く表示されたn件の製品(前章の文章と並べ替えられたものは多くない)
viewItemでは、すべての商品の閲覧回数(負数)を記録しています
conn.zincrby("viewed:", -1, item);
では、n日後になると、このviewedのデータ項目が多くなり、すべての商品の閲覧回数を常に保存する必要はありません.
だから
では、どうすればいいのでしょうか.どうやって私のプロジェクトに統合しますか?私のプロジェクトはstruts 2を使って開発されました.
お兄さん、遮断器というものがあるのを知らないのですか.interceptor?
これを見てください.http://www.2cto.com/kf/201506/408009.html
これはspringmvcですか?strutsはどうやって使いますか?
ばかだ!
struts 2のブロッキングでrequestとresponseを手に入れないの?
キャッシュするのは次のurlのような形ですhttp://test.com/shwoItem?item=itemX
せっけい案
最初のドメイン、zsetタイプの------keyはviewed:userSessionid保管されているのは、商品idとユーザーがこの商品を表示するときのtimestampです.
2番目のドメインは、zsetタイプの------viewedであってもよい.
メンバーは商品id(グローバル範囲内)、scoreは商品がユーザ(グローバル範囲内)に閲覧された回数(負数)である
3番目のドメイン、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 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;
}
キャッシュリクエストの実装
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([email protected])
* @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");
}
@Test
public 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
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;
}
@Override
public 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 block
e.printStackTrace();
}
}
}
}
システムが起動すると、このスレッドはずっと実行されます.では、どうすればいいのでしょうか.どうやって私のプロジェクトに統合しますか?私のプロジェクトはstruts 2を使って開発されました.
お兄さん、遮断器というものがあるのを知らないのですか.interceptor?
これを見てください.http://www.2cto.com/kf/201506/408009.html
これはspringmvcですか?strutsはどうやって使いますか?
ばかだ!
struts 2のブロッキングでrequestとresponseを手に入れないの?