欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringBoot+Redis Bitmap實現(xiàn)活躍用戶統(tǒng)計

 更新時間:2023年11月17日 10:40:25   作者:myprince003  
Redis的Bitmap數(shù)據(jù)結(jié)構(gòu)是一種緊湊的位圖,它可以用于實現(xiàn)各種場景,其中統(tǒng)計活躍用戶是一種經(jīng)典的業(yè)務(wù)場景,下面我們就來學(xué)習(xí)一下SpringBoot如何利用Redis中的Bitmap實現(xiàn)活躍用戶統(tǒng)計吧

前言

Redis的Bitmap數(shù)據(jù)結(jié)構(gòu)是一種緊湊的位圖,它可以用于實現(xiàn)各種場景,其中統(tǒng)計活躍用戶是一種經(jīng)典的業(yè)務(wù)場景。

實現(xiàn)原理是,通過將每個用戶表示為一個位,從而跟蹤用戶的活躍狀態(tài),使用位圖記錄用戶每天是否登錄,并計算月度或年度活躍用戶數(shù)。

案例代碼

以下是一個小例子,可以看到,使用SpringDataRedis,可以很輕松的實現(xiàn)BitMap的操作。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.BitSet;

@Service
public class UserLoginService {

    // 用戶登錄記錄的鍵前綴
    private static final String LOGIN_KEY_PREFIX = "login:"; 
    // 月份格式化器
    private static final DateTimeFormatter MONTH_FORMATTER = DateTimeFormatter.ofPattern("yyyyMM"); 
    // 年份格式化器
    private static final DateTimeFormatter YEAR_FORMATTER = DateTimeFormatter.ofPattern("yyyy"); 

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    /**
     * 記錄用戶登錄
     *
     * @param userId 用戶ID
     */
    public void recordLogin(String userId) {

        // 獲取存儲當(dāng)天用戶登錄信息的鍵
        String loginKey = getLoginKey(); 
        // 計算位圖偏移量,對應(yīng)用戶ID的哈希碼
        int bitOffset = getUserIdHashCode(userId); 
        // 將用戶ID對應(yīng)的位設(shè)置為1,表示用戶登錄
        redisTemplate.opsForValue().setBit(loginKey, bitOffset, true); 
    }

    /**
     * 獲取月度活躍用戶統(tǒng)計數(shù)據(jù)
     *
     * @return 月度活躍用戶統(tǒng)計數(shù)據(jù)
     */
    public BitSet getMonthlyActiveUsers() {

        // 獲取存儲月度活躍用戶信息的鍵
        String monthlyKey = getMonthlyKey(); 
        // 從Redis中獲取位圖數(shù)據(jù)
        return retrieveBitSet(monthlyKey); 
    }

    /**
     * 獲取年度活躍用戶統(tǒng)計數(shù)據(jù)
     *
     * @return 年度活躍用戶統(tǒng)計數(shù)據(jù)
     */
    public BitSet getYearlyActiveUsers() {

        // 獲取存儲年度活躍用戶信息的鍵
        String yearlyKey = getYearlyKey(); 
        // 從Redis中獲取位圖數(shù)據(jù)
        return retrieveBitSet(yearlyKey); 
    }

    /**
     * 獲取存儲當(dāng)天用戶登錄信息的鍵
     */
    private String getLoginKey() {

        LocalDate today = LocalDate.now();
        String dateKey = today.format(DateTimeFormatter.ISO_DATE);
        return LOGIN_KEY_PREFIX + dateKey;
    }

    /**
     * 計算用戶ID的哈希碼,保證非負(fù)數(shù)并適應(yīng)位圖長度
     */
    private int getUserIdHashCode(String userId) {

        int hashCode = userId.hashCode();
        // 1073741823是Redis位圖最大支持長度(2^30-1),可根據(jù)實際需求調(diào)整
        return Math.abs(hashCode % 1073741823); 
    }

    /**
     * 獲取存儲月度活躍用戶信息的鍵
     */
    private String getMonthlyKey() {

        LocalDate today = LocalDate.now();
        String monthKey = today.format(MONTH_FORMATTER);
        return LOGIN_KEY_PREFIX + "monthly:" + monthKey;
    }

    /**
     * 獲取存儲年度活躍用戶信息的鍵
     */
    private String getYearlyKey() {

        LocalDate today = LocalDate.now();
        String yearKey = today.format(YEAR_FORMATTER);
        return LOGIN_KEY_PREFIX + "yearly:" + yearKey;
    }

    /**
     * 從Redis中獲取位圖數(shù)據(jù)
     */
    private BitSet retrieveBitSet(String key) {

        // 獲取存儲在Redis中的位圖數(shù)據(jù)
        byte[] bytes = (byte[]) redisTemplate.opsForValue().get(key); 
        if (bytes != null) {
            // 將字節(jié)數(shù)組轉(zhuǎn)換為BitSet
            return BitSet.valueOf(bytes); 
        } else {
            // 若不存在,則返回空的BitSet
            return new BitSet(); 
        }
    }
}

其中有幾個地方解釋一下:

1、recordLogin方法用于記錄用戶登錄情況。每天的登錄情況被保存在以"login:日期"為鍵的位圖中,用戶的登錄狀態(tài)由位圖中對應(yīng)的位表示;

2、countMonthlyActiveUsers方法用于計算月度活躍用戶數(shù)量。每個月的活躍用戶數(shù)保存在以"login:monthly:年月"為鍵的位圖中,通過Redis的bitCount方法統(tǒng)計位圖中置為1的位數(shù),即月度活躍用戶數(shù);

3、ountYearlyActiveUsers方法用于計算年度活躍用戶數(shù)量,原理同上,只是統(tǒng)計的鍵變?yōu)?quot;login:yearly:年份";

4、getLoginKey、getUserIdHashCode、getMonthlyKey和getYearlyKey是輔助方法,負(fù)責(zé)生成對應(yīng)的Redis鍵或計算用戶ID的哈希碼。

轉(zhuǎn)換

上面的例子最終返回的是BitSet對象,通過這個對象我們經(jīng)過轉(zhuǎn)換后可以獲取到許多經(jīng)典的統(tǒng)計數(shù)據(jù),這里列舉一些經(jīng)典常用的統(tǒng)計結(jié)果示例。

大家可以根據(jù)這里面列舉的統(tǒng)計數(shù)據(jù),針對上面的代碼進行替換,得到自己想要的結(jié)果。

import java.util.BitSet;

// 獲取月度活躍用戶統(tǒng)計數(shù)據(jù)
BitSet monthlyActiveUsers = userLoginService.getMonthlyActiveUsers();

// 獲取年度活躍用戶統(tǒng)計數(shù)據(jù)
BitSet yearlyActiveUsers = userLoginService.getYearlyActiveUsers();

// 統(tǒng)計月度活躍用戶數(shù)量
int monthlyActiveUserCount = monthlyActiveUsers.cardinality();

// 統(tǒng)計年度活躍用戶數(shù)量
int yearlyActiveUserCount = yearlyActiveUsers.cardinality();

// 判斷某個用戶是否為月度活躍用戶
String userId = "user123";
boolean isMonthlyActiveUser = monthlyActiveUsers.get(userLoginService.getUserIdHashCode(userId));

// 判斷某個用戶是否為年度活躍用戶
boolean isYearlyActiveUser = yearlyActiveUsers.get(userLoginService.getUserIdHashCode(userId));

// 輸出統(tǒng)計結(jié)果
System.out.println("月度活躍用戶數(shù)量: " + monthlyActiveUserCount);
System.out.println("年度活躍用戶數(shù)量: " + yearlyActiveUserCount);
System.out.println("用戶user123是否為月度活躍用戶: " + isMonthlyActiveUser);
System.out.println("用戶user123是否為年度活躍用戶: " + isYearlyActiveUser);

總結(jié)

Redis的Bitmap數(shù)據(jù)結(jié)構(gòu)非常靈活,可以根據(jù)具體需求實現(xiàn)各種位操作,但平時在項目中很多人沒有機會使用到,這個案例非常簡單,希望能讓大家對此有個認(rèn)識,未來用到了不會感到陌生。

以上就是SpringBoot+Redis Bitmap實現(xiàn)活躍用戶統(tǒng)計的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot Redis Bitmap用戶統(tǒng)計的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Java Proxy機制詳細(xì)解讀

    Java Proxy機制詳細(xì)解讀

    這篇文章主要介紹了Java Proxy機制詳細(xì)解讀,還是非常不錯的,這里分享給大家,需要的朋友可以參考下。
    2017-10-10
  • 通過實例了解java checked和unchecked異常

    通過實例了解java checked和unchecked異常

    這篇文章主要介紹了通過實例了解checked和unchecked異常,Java異常分為兩種類型,checked異常和unchecked異常,另一種叫法是異常和錯誤。下面小編就帶大家來一起學(xué)習(xí)一下吧
    2019-06-06
  • Java中可變長度參數(shù)代碼詳解

    Java中可變長度參數(shù)代碼詳解

    這篇文章主要介紹了Java中可變長度參數(shù)代碼詳解,涉及了實參個數(shù)可變的定義方法,數(shù)組包裹實參等幾個問題,具有一定參考價值,需要的朋友可以了解下。
    2017-12-12
  • java實現(xiàn)微信支付結(jié)果通知

    java實現(xiàn)微信支付結(jié)果通知

    這篇文章主要為大家詳細(xì)介紹了java實現(xiàn)微信支付結(jié)果通知,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-01-01
  • springboot自動裝配原理初識

    springboot自動裝配原理初識

    這篇文章主要介紹了springboot自動裝配原理的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)使用springboot,感興趣的朋友可以了解下
    2021-04-04
  • Java中的List接口實現(xiàn)類解析

    Java中的List接口實現(xiàn)類解析

    這篇文章主要介紹了Java中的List接口實現(xiàn)類解析,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • 通過java記錄數(shù)據(jù)持續(xù)變化時間代碼解析

    通過java記錄數(shù)據(jù)持續(xù)變化時間代碼解析

    這篇文章主要介紹了通過java記錄數(shù)據(jù)持續(xù)變化時間代碼解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-01-01
  • 淺談為什么Java里面String類是不可變的

    淺談為什么Java里面String類是不可變的

    這篇文章主要介紹了為什么Java里面String類是不可變的,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-03-03
  • springboot項目如何使用切面記錄用戶操作日志

    springboot項目如何使用切面記錄用戶操作日志

    這篇文章主要介紹了springboot項目如何使用切面記錄用戶操作日志,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-10-10
  • Java中的ReentrantLock、ReentrantReadWriteLock、StampedLock詳解

    Java中的ReentrantLock、ReentrantReadWriteLock、StampedLock詳解

    這篇文章主要介紹了Java中的ReentrantLock、ReentrantReadWriteLock、StampedLock詳解,讀寫鎖:一個資源能夠被多個讀線程訪問,或者被一個寫線程訪問但是不能同時存在讀寫線程,需要的朋友可以參考下
    2024-01-01

最新評論