最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Redis應(yīng)用之簽到的使用

 更新時間:2024年05月09日 08:30:42   作者:沉河不浮  
在很多時候,我們遇到用戶簽到的場景,本文主要介紹了Redis應(yīng)用之簽到的使用,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

位圖由一系列二進制位組成,每個位可以被設(shè)置為1或0,當(dāng)我們在處理需要高效存儲和操作大量二進制位數(shù)據(jù)的適合,位圖是一個非常有用的工具。
位圖操作命令有:

  • SETBIT:設(shè)置位圖中指定位置的位的值。可以將位設(shè)置為 0 或 1。
  • GETBIT:獲取位圖中指定位置的位的值。
  • BITCOUNT:計算位圖中置為 1 的位的數(shù)量。
  • BITOP:對多個位圖執(zhí)行邏輯運算(AND、OR、XOR、NOT)。
  • BITFIELD:執(zhí)行復(fù)雜的位字段操作,允許你在位圖上進行位級別的讀寫操作。

其中,用的最多的是前三個操作,示例如下:

image.png

位圖的應(yīng)用十分廣泛,包括但不限于以下幾方面:

  • 統(tǒng)計用戶活躍度:可以使用位圖追蹤用戶的登錄活動,每個用戶對應(yīng)一個位圖,每天的登錄狀態(tài)可以用一個二進制位表示,通過 BITOP 命令可以計算多個用戶的交集,從而得到活躍用戶的統(tǒng)計信息。
  • 數(shù)據(jù)壓縮:位圖可以高效地存儲大量的二進制數(shù)據(jù),比如布隆過濾器(Bloom Filter)就是基于位圖實現(xiàn)的一種數(shù)據(jù)結(jié)構(gòu),用于快速判斷元素是否存在。
  • 事件計數(shù):可以使用位圖記錄每天不同時間段的事件發(fā)生情況,比如網(wǎng)站的訪問量,每個時間段對應(yīng)一個位圖,每次事件發(fā)生時將對應(yīng)的位設(shè)置為 1,通過 BITCOUNT 命令可以計算出每個時間段的事件數(shù)量。
  • 權(quán)限管理:可以使用位圖來管理用戶的權(quán)限,每個用戶對應(yīng)一個位圖,每個權(quán)限對應(yīng)一個二進制位,通過 BITOP 命令可以進行權(quán)限的并集、交集等操作。

RedisTemplate操作位圖

在之前的幾篇文章中,我們總結(jié)了一個Redis工具類,但是那個工具類中,并沒有和位圖相關(guān)的操作,這里添加和位圖操作相關(guān)的方法:

   // value: true為1, false為0
    public boolean setBit(String key, int offset, boolean value) {
        return redisTemplate.opsForValue().setBit(key, offset, value);
    }

    public boolean getBit(String key, int offset) {
        return redisTemplate.opsForValue().getBit(key, offset);
    }

    /**
     * 統(tǒng)計對應(yīng)值為1 的數(shù)量
     * @param key
     * @return
     */
    public long bitCount(String key) {
        if (StringUtils.isEmpty(key)) {
            return 0L;
        }
        return redisTemplate.execute((RedisCallback<Long>) con -> con.bitCount(key.getBytes()));
    }

    /**
     * 統(tǒng)計在字節(jié)范圍內(nèi),對應(yīng)值為1的數(shù)量
     * @param key
     * @param start
     * @param end
     * @return
     */
    public Long bitCount(String key, long start, long end) {
        return redisTemplate.execute((RedisCallback<Long>) con -> con.bitCount(key.getBytes(), start, end));
    }

添加測試類,用于測試位圖操作:

package org.example;

import org.example.util.RedisUtils;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
public class RedisBitMapTest {
    @Autowired
    private RedisUtils redisUtils;

    @Test
    public void testBitMap() {
        redisUtils.setBit("bit", 0, true);
        redisUtils.setBit("bit", 1, true);
        redisUtils.setBit("bit", 3, true);
        redisUtils.setBit("bit", 7, true);
        System.out.println(redisUtils.bitCount("bit"));

    }
}

執(zhí)行結(jié)果如下:

image.png

我們通過Redis可視化工具,查看bit的值,可以看出其二進制值與我們操作的一致

image.png

位圖應(yīng)用之簽到

在很多時候,我們遇到用戶簽到的場景,用戶進入應(yīng)用時,獲取用戶當(dāng)天的簽到情況,如果沒有簽到,用戶可以簽到,一般這種功能,可以通過set數(shù)據(jù)結(jié)構(gòu)或bitMap來實現(xiàn),但bitMap和set相比,其占用的空間更小,因此我們選擇使用bitMap來實現(xiàn)簽到的功能。
SignService:

package org.example.util;

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

import java.time.LocalDate;
import java.util.List;

@Service
public class SignService {
    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    /**
     * 簽到
     * @param id
     */
    public void sign(Integer id) {
        LocalDate now = LocalDate.now();
        String key = buildCacheKey(id, now);
        int dayOfMonth = now.getDayOfMonth();

        // 簽到
        redisUtils.setBit(key, dayOfMonth, true);
    }

    /**
     * 判斷是否簽到
     */
    public boolean isSign(Integer id) {
        LocalDate now = LocalDate.now();
        String key = buildCacheKey(id, now);
        int dayOfMonth = now.getDayOfMonth();
        return redisUtils.getBit(key, dayOfMonth);
    }

    /**
     * 獲取當(dāng)月的簽到次數(shù)
     * @param id
     * @return
     */
    public Long getSignCountOfThisMonth(Integer id) {
        LocalDate now = LocalDate.now();
        String key = buildCacheKey(id, now);
        int dayOfMonth = now.getDayOfMonth();
        List<Long> result = redisTemplate.opsForValue().bitField(key,
                BitFieldSubCommands.create()
                        .get(BitFieldSubCommands.BitFieldType.unsigned(dayOfMonth)).valueAt(1));
        if (result == null || result.isEmpty()) {
            return 0L;
        }
        Long num = result.get(0);
        if (num == null || num == 0) {
            return 0L;
        }

        String binaryStr = Long.toString(num, 2);

        long count = 0;
        for (int i = 0; i < binaryStr.length(); i++) {
            char ch = binaryStr.charAt(i);
            if (ch == '1') {
                count ++;
            }
        }
        return count;
    }

    /**
     * 獲取本月連續(xù)簽到次數(shù)
     * @param id
     * @return
     */
    public Long getContinuousSignCountOfThisMonth(Integer id) {
        LocalDate now = LocalDate.now();
        String key = buildCacheKey(id, now);
        int dayOfMonth = now.getDayOfMonth();
        List<Long> result = redisTemplate.opsForValue().bitField(key,
                BitFieldSubCommands.create()
                        .get(BitFieldSubCommands.BitFieldType.unsigned(dayOfMonth)).valueAt(1));
        if (result == null || result.isEmpty()) {
            return 0L;
        }
        Long num = result.get(0);
        if (num == null || num == 0) {
            return 0L;
        }

        long count = 0;
        while (true) {
            if ((num & 1) == 0) {
                break;
            } else {
                count ++;
            }
            num >>>= 1;
        }
        return count;
    }

    private String buildCacheKey(Integer id, LocalDate localDate) {
        int year = localDate.getYear();
        int monthValue = localDate.getMonthValue();
        String key = "sign:" + year + ":" + monthValue + ":" + id;
        return key;
    }
}

測試代碼如下:

@Autowired
    private SignService signService;

    @Test
    public void testSign() {
        // 簽到
        signService.sign(1);

        // 判斷是否簽到
        System.out.println("是否簽到:" + signService.isSign(1));

        // 獲取當(dāng)月的簽到次數(shù)
        System.out.println("當(dāng)月的簽到次數(shù):" + signService.getSignCountOfThisMonth(1));

        // 獲取當(dāng)月的連續(xù)簽到次數(shù)
        System.out.println("當(dāng)月連續(xù)簽到次數(shù):" + signService.getContinuousSignCountOfThisMonth(1));
    }

運行結(jié)果如下:

image.png

到此這篇關(guān)于Redis應(yīng)用之簽到的使用的文章就介紹到這了,更多相關(guān)Redis 簽到內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 分段存儲Redis鍵值對的方法詳解

    分段存儲Redis鍵值對的方法詳解

    Redis是一種開源的、基于內(nèi)存的數(shù)據(jù)結(jié)構(gòu)存儲系統(tǒng),它可以用作數(shù)據(jù)庫、緩存和消息中間件,Redis最常用的功能之一就是其鍵值對數(shù)據(jù)模型,本文介紹針對一個value過長的鍵值對,如何分段存儲,需要的朋友可以參考下
    2025-01-01
  • 使用攔截器+Redis實現(xiàn)接口冪思路詳解

    使用攔截器+Redis實現(xiàn)接口冪思路詳解

    這篇文章主要介紹了使用攔截器+Redis實現(xiàn)接口冪等,接口冪等有很多種實現(xiàn)方式,攔截器/AOP+Redis,攔截器/AOP+本地緩存等等,本文講解一下通過攔截器+Redis實現(xiàn)冪等的方式,需要的朋友可以參考下
    2023-08-08
  • Redis中ziplist壓縮列表的實現(xiàn)

    Redis中ziplist壓縮列表的實現(xiàn)

    本文主要介紹了Redis中ziplist壓縮列表的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-06-06
  • Redis設(shè)置永久密碼方式

    Redis設(shè)置永久密碼方式

    找到Redis安裝目錄下的redis.windows.conf文件,搜索并設(shè)置requirepass參數(shù)為自定義密碼,保存修改后重啟服務(wù),以增強安全性,此為個人經(jīng)驗,供參考
    2025-07-07
  • Redis利用原子操作(INCR,DECR)實現(xiàn)分布式計數(shù)器

    Redis利用原子操作(INCR,DECR)實現(xiàn)分布式計數(shù)器

    在分布式系統(tǒng)中,由于多個服務(wù)實例需要共享和修改同一個計數(shù)值,實現(xiàn)一個準確、高效的分布式計數(shù)器至關(guān)重要,下面我們就來看看具體實現(xiàn)方法吧
    2025-07-07
  • Redis實戰(zhàn)之Redis實現(xiàn)異步秒殺優(yōu)化詳解

    Redis實戰(zhàn)之Redis實現(xiàn)異步秒殺優(yōu)化詳解

    這篇文章主要給大家介紹了Redis實戰(zhàn)之Redis實現(xiàn)異步秒殺優(yōu)化方法,文章通過圖片和代碼介紹的非常詳細,對大家的學(xué)習(xí)或工作有一定的幫助,感興趣的同學(xué)可以自己動手試一下
    2023-09-09
  • 避免Redis緩存擊穿的有效方式

    避免Redis緩存擊穿的有效方式

    本文探討了SpringBoot中防止Redis緩存擊穿的策略,包括設(shè)置隨機過期時間、使用互斥鎖、布隆過濾器和永不過期策略等,并分析了各種策略的優(yōu)缺點和適用場景,通過合理選擇和調(diào)整,可以提高應(yīng)用的可靠性和用戶體驗,實踐中需要持續(xù)優(yōu)化以應(yīng)對不斷變化的技術(shù)和業(yè)務(wù)環(huán)境
    2026-04-04
  • redis發(fā)布訂閱_動力節(jié)點Java學(xué)院整理

    redis發(fā)布訂閱_動力節(jié)點Java學(xué)院整理

    這篇文章主要介紹了redis發(fā)布訂閱,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-08-08
  • Redis接口訪問優(yōu)化的方法步驟

    Redis接口訪問優(yōu)化的方法步驟

    本文基于之前的Redis接口訪問進行優(yōu)化,引入了接口防抖功能,通過時間段參數(shù)限制接口調(diào)用頻率,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-10-10
  • 詳解redis desktop manager安裝及連接方式

    詳解redis desktop manager安裝及連接方式

    這篇文章主要介紹了redis desktop manager安裝及連接方式,本文圖文并茂給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下
    2019-09-09

最新評論

屏东市| 饶平县| 安塞县| 常德市| 阳高县| 冕宁县| 夏河县| 辽宁省| 曲沃县| 太白县| 射阳县| 呼玛县| 含山县| 松溪县| 湘乡市| 星子县| 高淳县| 衡南县| 桂阳县| 离岛区| 津市市| 兰州市| 肇庆市| 万全县| 林西县| 鄱阳县| 八宿县| 枞阳县| 龙海市| 阜阳市| 乌拉特中旗| 玉山县| 台北县| 灯塔市| 平乡县| 长治县| 叙永县| 炉霍县| 涡阳县| 紫阳县| 邓州市|