<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

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

          共 4667字,需瀏覽 10分鐘

           ·

          2024-05-22 10:30

          來源:juejin.cn/post/7356065093060427816

          ?? 歡迎加入小哈的星球 ,你將獲得: 專屬的項(xiàng)目實(shí)戰(zhàn) / Java 學(xué)習(xí)路線 / 一對一提問 / 學(xué)習(xí)打卡 /  每月贈書


          新項(xiàng)目:仿小紅書(微服務(wù)架構(gòu))正在更新中... , 全棧前后端分離博客項(xiàng)目 2.0 版本完結(jié)啦, 演示鏈接http://116.62.199.48/ 。全程手摸手,后端 + 前端全棧開發(fā),從 0 到 1 講解每個功能點(diǎn)開發(fā)步驟,1v1 答疑,直到項(xiàng)目上線。目前已更新了261小節(jié),累計41w+字,講解圖:1806張,還在持續(xù)爆肝中.. 后續(xù)還會上新更多項(xiàng)目,目標(biāo)是將Java領(lǐng)域典型的項(xiàng)目都整一波,如秒殺系統(tǒng), 在線商城, IM即時通訊,Spring Cloud Alibaba 等等,戳我加入學(xué)習(xí),已有1400+小伙伴加入(早鳥價超低)


          一、前言

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

          核心方法是這四個:zaddzrangeByScorezremrangeByScorezrem

          圖片

          二、實(shí)現(xiàn)步驟

          1. 如何認(rèn)定用戶是否在線?

          認(rèn)定用戶在線的條件一般跟網(wǎng)站有關(guān),如果網(wǎng)站需要登錄才能進(jìn)入,那么這種網(wǎng)站就是根據(jù)用戶的token令牌有效性判斷是否在線;

          如果網(wǎng)站是公開的,是那種不需要登錄就可以瀏覽的,那么這種網(wǎng)站一般就需要自定一個規(guī)則來識別用戶,也有很多方式實(shí)現(xiàn)如IP、deviceId、瀏覽器指紋,推薦使用瀏覽器指紋的方式實(shí)現(xiàn)。

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

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

          // 安裝: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了,當(dāng)用戶訪問網(wǎng)站的時候,將這個ID放到訪問鏈接的Cookie或者h(yuǎn)eader中傳到后臺,后端服務(wù)根據(jù)這個ID標(biāo)示用戶。

          2. zadd命令添加在線用戶

          1)zadd命令介紹

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

          • key:有序集合的名稱。
          • score1、score2 等:分?jǐn)?shù)值,可以是整數(shù)值或雙精度浮點(diǎn)數(shù)。
          • member1、member2 等:要添加到有序集合的成員。

          例子:向名為 myzset 的有序集合中添加一個成員:ZADD myzset 1 "one"

          2)添加在線用戶標(biāo)識到有序集合中

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

          由于一個用戶可能戶會重復(fù)登錄,這就導(dǎo)致userToken也會重復(fù),但為了不重復(fù)計算這個用戶的訪問次數(shù),zadd命令的第二個參數(shù)很好的解決了這個問題。

          我這里的邏輯是:每次添加一個在線用戶時,利用當(dāng)前時間加上過期時間計算出一個分?jǐn)?shù),可以有效保證當(dāng)前用戶只會存在一個最新的登錄態(tài)。

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

          1)zrangeByScore命令介紹

          • key:指定的有序集合的名字。
          • min 和 max:定義了查詢的分?jǐn)?shù)范圍,也可以是 -inf 和 +inf(分別表示“負(fù)無窮大”和“正無窮大”)。

          例子:查詢分?jǐn)?shù)在 1 到 3之間的所有成員:ZRANGEBYSCORE myzset 1 3

          2)查詢當(dāng)前所有的在線用戶

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

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

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

          1)zremrangeByScore命令介紹

          • key:指定的有序集合的名字。
          • min 和 max:定義了查詢的分?jǐn)?shù)范圍,也可以是 -inf 和 +inf(分別表示“負(fù)無窮大”和“正無窮大”)。

          例子:刪除分?jǐn)?shù)在 1 到 3之間的所有成員:ZREMRANGEBYSCORE myzset 1 3

          2)定時清除在線用戶

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

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

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

          1)zrem命令介紹

          • key:指定的有序集合的名字。
          • members:需要刪除的成員

          例子:刪除名為xxx的成員:ZREM myzset "xxx"

          2)定時清除在線用戶

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

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

          三、小結(jié)一下

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

          ?? 歡迎加入小哈的星球 ,你將獲得: 專屬的項(xiàng)目實(shí)戰(zhàn) / Java 學(xué)習(xí)路線 / 一對一提問 / 學(xué)習(xí)打卡 /  每月贈書


          新項(xiàng)目:仿小紅書(微服務(wù)架構(gòu))正在更新中... , 全棧前后端分離博客項(xiàng)目 2.0 版本完結(jié)啦, 演示鏈接http://116.62.199.48/ 。全程手摸手,后端 + 前端全棧開發(fā),從 0 到 1 講解每個功能點(diǎn)開發(fā)步驟,1v1 答疑,直到項(xiàng)目上線。目前已更新了261小節(jié),累計41w+字,講解圖:1806張,還在持續(xù)爆肝中.. 后續(xù)還會上新更多項(xiàng)目,目標(biāo)是將Java領(lǐng)域典型的項(xiàng)目都整一波,如秒殺系統(tǒng), 在線商城, IM即時通訊,Spring Cloud Alibaba 等等,戳我加入學(xué)習(xí),已有1400+小伙伴加入(早鳥價超低)



              
                 

          1. 我的私密學(xué)習(xí)小圈子~

          2. 你還在使用 WebSocket 實(shí)現(xiàn)實(shí)時消息推送嗎?

          3. 高性能必殺技:Java中的池化技術(shù)

          4. 官方推出了 Spring AI 框架,Java集成 AI 不再是難事!

          最近面試BAT,整理一份面試資料Java面試BATJ通關(guān)手冊,覆蓋了Java核心技術(shù)、JVM、Java并發(fā)、SSM、微服務(wù)、數(shù)據(jù)庫、數(shù)據(jù)結(jié)構(gòu)等等。

          獲取方式:點(diǎn)“在看”,關(guān)注公眾號并回復(fù) Java 領(lǐng)取,更多內(nèi)容陸續(xù)奉上。

          PS:因公眾號平臺更改了推送規(guī)則,如果不想錯過內(nèi)容,記得讀完點(diǎn)一下在看,加個星標(biāo),這樣每次新文章推送才會第一時間出現(xiàn)在你的訂閱列表里。

          點(diǎn)“在看”支持小哈呀,謝謝啦

          瀏覽 127
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  日翰欧美三级片在线播放 | 亚洲操屄| 男人天堂v在线 | 色五月在线视频 | 久草热人妻 |