1. 如何優(yōu)雅的實現(xiàn)在線人數(shù)統(tǒng)計功能?

        共 4818字,需瀏覽 10分鐘

         ·

        2024-07-18 09:19

        往期熱門文章:

        
           

        1、JetBrains再出手,這波秀翻了。。
        2、FullGC 40次/天到10天1次,真牛B??!
        3、不服不行,這才是后端API接口應該有的樣子!
        4、一個強大的分布式鎖框架——Lock4j
        5、Stream很好,Map很酷,但答應我別用toMap()


        前言


        在線人數(shù)統(tǒng)計這個功能相信大家一眼就明白是啥,這個功能不難做,實現(xiàn)的方式也很多,這里說一下我常使用的方式:使用Redis的有序集合(zset)實現(xiàn)。核心方法是這四個:zaddzrangeByScore、zremrangeByScore、zrem。



        實現(xiàn)步驟







        1、如何認定用戶是否在線?

        認定用戶在線的條件一般跟網(wǎng)站有關,如果網(wǎng)站需要登錄才能進入,那么這種網(wǎng)站就是根據(jù)用戶的token令牌有效性判斷是否在線;如果網(wǎng)站是公開的,是那種不需要登錄就可以瀏覽的,那么這種網(wǎng)站一般就需要自定一個規(guī)則來識別用戶,也有很多方式實現(xiàn)如IPdeviceId、瀏覽器指紋,推薦使用瀏覽器指紋的方式實現(xiàn)。

        瀏覽器指紋可能包括以下信息的組合:用戶代理字符串 (User-Agent string)、HTTP請求頭信息、屏幕分辨率和顏色深度、時區(qū)和語言設置、瀏覽器插件詳情等。現(xiàn)成的JavaScript庫,像 FingerprintJS 或 ClientJS,可以幫助簡化這個過程,因為它們已經(jīng)實現(xiàn)了收集上述信息并生成唯一標識的算法。

        使用起來也很簡單,如下:

        // 安裝:npm install @fingerprintjs/fingerprintjs

        // 使用示例:
        import FingerprintJS from '@fingerprintjs/fingerprintjs';

        // 初始化指紋JS Library
        FingerprintJS.load().then(fp => {
          // 獲取訪客ID
          fp.get().then(result => {
            const visitorId = result.visitorId;
            console.log(visitorId);
          });
        });

        這樣就可以獲取一個訪問公開網(wǎng)站的用戶的唯一ID了,當用戶訪問網(wǎng)站的時候,將這個ID放到訪問鏈接的Cookie或者header中傳到后臺,后端服務根據(jù)這個ID標示用戶。


        2、zadd命令添加在線用戶

        zadd命令介紹 zadd命令有三個參數(shù)

        ?

        key:有序集合的名稱。score1、score2 等:分數(shù)值,可以是整數(shù)值或雙精度浮點數(shù)。member1、member2 等:要添加到有序集合的成員。例子:向名為 myzset 的有序集合中添加一個成員:ZADD myzset 1 "one"

        添加在線用戶標識到有序集合中

        // expireTime給用戶令牌設置了一個過期時間
        LocalDateTime expireTime = LocalDateTime.now().plusSeconds(expireTimeout);
        String expireTimeStr = DateUtil.formatFullTime(expireTime);
        // 添加用戶token到有序集合中
        redisService.zadd("user.active", Double.parseDouble(expireTimeStr), userToken);
        ?

        由于一個用戶可能戶會重復登錄,這就導致userToken也會重復,但為了不重復計算這個用戶的訪問次數(shù),zadd命令的第二個參數(shù)很好的解決了這個問題。我這里的邏輯是:每次添加一個在線用戶時,利用當前時間加上過期時間計算出一個分數(shù),可以有效保證當前用戶只會存在一個最新的登錄態(tài)。


        3、zrangeByScore命令查詢在線人數(shù)

        zrangeByScore命令介紹

        ?

        key:指定的有序集合的名字。min 和 max:定義了查詢的分數(shù)范圍,也可以是 -inf 和 +inf(分別表示“負無窮大”和“正無窮大”)。例子:查詢分數(shù)在 1 到 3之間的所有成員:ZRANGEBYSCORE myzset 1 3

        查詢當前所有的在線用戶

        // 獲取當前的日期
        String now = DateUtil.formatFullTime(LocalDateTime.now());
        // 查詢當前日期到"+inf"之間所有的用戶
        Set<String> userOnlineStringSet = redisService.zrangeByScore("user.active", now, "+inf");
        ?

        利用zrangeByScore方法可以查詢這個有序集合指定范圍內(nèi)的用戶,這個userOnlineStringSet也就是在線用戶集,它的size就是在線人數(shù)了。


        4、zremrangeByScore命令定時清除在線用戶

        zremrangeByScore命令介紹

        ?

        key:指定的有序集合的名字。min 和 max:定義了查詢的分數(shù)范圍,也可以是 -inf 和 +inf(分別表示“負無窮大”和“正無窮大”)。例子:刪除分數(shù)在 1 到 3之間的所有成員:ZREMRANGEBYSCORE myzset 1 3

        定時清除在線用戶

        // 獲取當前的日期
        String now = DateUtil.formatFullTime(LocalDateTime.now());
        // 清除當前日期到"-inf"之間所有的用戶
        redisService.zremrangeByScore(""user.active"","-inf", now);      
        ?

        由于有序集合不會自動清理下線的用戶,所以這里我們需要寫一個定時任務去定時刪除下線的用戶。


        5、zrem命令用戶退出登錄時刪除成員

        zrem命令介紹

        ?

        key:指定的有序集合的名字。members:需要刪除的成員 例子:刪除名為xxx的成員:ZREM myzset "xxx"

        定時清除在線用戶

        // 刪除名為xxx的成員
        redisService.zrem("user.active""xxx");      
        ?

        刪除 zset中的記錄,確保主動退出的用戶下線。



        小結一下





        這種方案的核心邏輯就是,創(chuàng)建一個在線用戶身份集合為key,利用用戶身份為member,利用過期時間為score,然后對這個集合進行增刪改查,實現(xiàn)起來還是比較巧妙和簡單的,大家有興趣可以試試看。


        文章來源:https://juejin.cn/post/7356065093060427816

           
        往期熱門文章:

        1、你合并代碼用 merge 還是用 rebase ?
        2、99%的時間里只使用這14個Git命令就夠了?。?!
        3、再見 Navicat ?不好意思,它免費了!
        4、@Transactional(readOnly=true)真的是提高性能的靈丹妙藥嗎?
        5、8種方案解決重復提交問題!
        6、教你用三種方式模擬兩個線程搶票
        7、MySQL中varchar(50)和varchar(500)區(qū)別是什么?
        8、頂級Javaer都在使用的類庫,真香!
        9、最適合程序員的畫圖工具?
        10、Logback 與 log4j2 性能哪個更強?

        瀏覽 323
        1點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        1點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
          
          

            1. 无码一二三四 | 干黄视频| 宝宝才两根手指就疼哭了怎么回事 | 国产日本在线 | 伊人久久大香线蕉 |