Redisオンラインユーザー設計
4858 ワード
二、redisキャッシュ設計
オンラインユーザーリストの設計方法ユーザ量が大きいためデータベースを用いてオンラインユーザを保存するとボトルネックの問題があり,システムの伸縮や拡張性などを考慮してredisをオンラインユーザキャッシュとして採用するが,最も簡単で乱暴な案はredisのlistにユーザを格納することであるが,ユーザ量指数が増加すると,Listのクエリー速度とページング速度は非常に遅い-ログイン時間に従ってクエリーをソートする場合、listスキームは処理しにくい-オンラインユーザーはセッション管理に基づいており、セッションが失効した後にredisに対応するパージ作業を通知する方法-セッションタイムアウト時間がredis keyと同期を維持する方法、すなわちセッションが失効した場合、redisに対応するキャッシュキーも失効する
1.1 list構造が適任でない
私達は1つの集合を採用して1ページのデータを保存して、例えば1ページの20条、全部で100ページ、5つの秩序の集合を生成して、OKはこのように1つのlistアクセスのデータの量が大きすぎる問題を解決して、秩序の集合で順序の問題を解決して、以下はコードで下の構想を説明します
//key ,loginTime ( ),userid ID
redis.zadd("pageNum",loginTime,userId);
// set
redis.set(userId,user);
// ,
public List getOnlineUser(int pageNum,boolean isAsc){
Set userIds = null;
List users = new ArrayList();
if(isAsc){
userIds = redis.zrange(zkey, 0, -1);//redis
}else{
userIds = redis.zrevrange(zkey, 0, -1);//redis
}
// userids ,
Iterator iterUserIds = userIds.iterator();
while(iterUserIds.hasNext()){
String userId = iterUserIds.next();
User user = redis.get(userId);
users.add(user);
}
return users;
}
まとめ:1つの秩序ある集合は1ページのデータですが、彼が保存しているメンバーkeyはユーザーIDで、数値はログイン時間で、本当のユーザーオブジェクトは簡単なsetだけで、それから秩序ある集合を遍歴してidで再取得して、秩序ある集合は冗長な集合で、私たちはメモリで設計の柔軟性を交換しました.
1.2 redis期限切れキー、redisキー、session同期の問題をクリアする方法.
次のいくつかのピット-順序付き集合のメンバーkeyは期限切れを設定できず、最も外部のkeyに対してのみ設定できます-リストのあるページをクリックすると、データ取得中にユーザーが期限切れになったかどうかを判断できます(グローバルセッションの判断によると、グローバルセッションの期限切れはキャッシュされたユーザーも効果がありません)が、これにより解決しにくい問題に直面します.例えば、総ページ数4、2ページ目と3ページ目で何人かのユーザーが失効した場合、2ページ目に戻ると1ページ未満のデータが表示されますが、総ページ数は4で、これは明らかに不合理です.解決策は,あるページのユーザをクリックしたときに集合を補ページ操作することであり,補ページ操作とは1ページ未満のときに埋め尽くすことであり,2ページ目に補が必要であれば,3ページ目以降のデータは1つの要素を配列削除して全体的に移動するという理屈である.データ量が大きすぎると移動する時間の複雑さも大きい.データ量が多いといえば、1つの集合で1万個のデータを保存することができ、フロントで1万個を表示することはできません.実際に記憶されているのは1万、仮想表示されているページは10または20で、22ページ目をめくると、実際のページ番号を推定することができます.以下のコードです.
/**
* ,virPageSize ( 10 20 ),pageNum ,
*pageSize
* 1 。
* @param pageNum
* @return
*/
private int calculatePageNum(int pageNum) {
int targetRow = pageNum*virPageSize;
if(targetRow%pageSize==0){
return targetRow%pageSize;
}
return (targetRow/pageSize)+1;
}
上記はredis失効問題をある程度解決することができ、オンラインリストを取得する際に失効クリアを判断したが、これはアクティブにトリガする必要があるため、以下ではタイミング検出メカニズムを採用する.まずsessionとredisの同期問題を解決しなければならない.プロジェクトではshiroが使用され、sessionとアクセスページを作成すると、それぞれshiro sessionDAOのdoCreateメソッドとdoReadSessionメソッドが呼び出され、doReadSesisonメソッドにアクセスするとredis keyにタイムアウト時間(expire)を再設定することができ、session同期に達し、最後に検出されたスレッドを通じてsessionの最後のアクセス時間を確認することができます.タイムアウト時間を減算してタイムアウトするかどうか.
秩序化された集合zadd(key,sessionTime,sessionId_startTime)は、数値が最後のアクセス時間であり、メンバーkeyがsessionid+の作成時間であり、その後、昇順ソートが集合の最初の最後のアクセス時間にフェッチされ、最初のタイムアウトがないことは、彼がその後タイムアウトしていないことを証明し、今回のサイクルをスキップします(ソートが過ぎたため).分割値sessionTimeはsessionDAOにアクセスしたときに再設定でき、クリアしたときにsessionIDがあるのでtoken、ユーザなどの情報を取得できます(自分でsessionIDに対応する情報、例えばsessionIDがkey、tokenオブジェクトが値)
*認証センターが強制的にオフラインになったユーザーがグローバルtokenを失効させ、秩序化されたセットの最後のアクセス時間が残っているシーンがあります.まだ有効期限が切れていない場合は、このようなデータをループして取得しても消去されません.*改良案:*一、前のデータをパーセンテージで消去し、所望のヒット率に達した後も消去を継続する2、ログアウトまたは強制ラインオフ時にセッションIDを取得し、整列集合中のメンバーをremove**
次のリンクは、Redisオンラインユーザー設計(ページングの問題を解決)です.https://blog.csdn.net/qq277165811/article/details/72781741
前編単点上陸
たんてんじょうりくせっけい
未完待続!!