Redisオンラインユーザー設計

4858 ワード

  • 二、redisキャッシュ設計
  • 1.1 list構造は
  • に適任ではない
  • 1.2 redis期限切れキー、redisキー、session同期の問題をどのようにクリアするか.



  • 二、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
    前編単点上陸
    たんてんじょうりくせっけい
    未完待続!!