《程序猿之Redis缓存实战 · 位图类型》

news2024/11/19 3:33:52

📢 大家好,我是 【战神刘玉栋】,有10多年的研发经验,致力于前后端技术栈的知识沉淀和传播。 💗

🌻 CSDN入驻不久,希望大家多多支持,后续会继续提升文章质量,绝不滥竽充数,欢迎多多交流。👍

文章目录

    • 位图(Bitmap)

位图(Bitmap)

【简介】

Bitmap 存储的是连续的二进制数字(0 和 1),通过 Bitmap, 只需要一个 bit 位来表示某个元素对应的值或者状态,key 就是对应元素本身 。我们知道 8 个 bit 可以组成一个 byte,所以 Bitmap 本身会极大的节省储存空间。

【应用场景】

需要保存状态信息(0/1 即可表示)的场景

● 举例:用户签到情况、活跃用户情况、用户行为统计(比如是否点赞过某个视频)。

● 相关命令:SETBIT、GETBIT、BITCOUNT、BITOP。

【基本操作】

setbit key offset val:给指定key的值的第offset赋值val 时间复杂度:O(1)
getbit key offset:获取指定key的第offset位 时间复杂度:O(1)
bitcount key start end:返回指定key中[ start,end ]中为1的数量 时间复杂度:O(n)
BITPOS key bit start end:查找字符串中第一个设置为1或0的位的位置

【实战 - 文章点赞】

使用 Redis 的 Bitmaps 来处理文章的点赞功能是一个非常合适的选择,尤其是在需要高效存储和快速查询的场景中。Bitmaps 允许你以位(bit)为单位存储数据,这样可以节省存储空间并提高性能。

为什么使用 Bitmaps?

  • 节省空间:每个用户的点赞状态只需要一个比特位(0 或 1),而不是存储整个用户 ID。
  • 高效查询:可以快速检查某个用户是否点赞,以及统计点赞总数。

示例说明:

假设我们有一个文章 ID 为 article:123 的文章,用户 ID 为 user:456,我们可以使用 Redis 的 Bitmaps 来记录用户的点赞状态。首先,使用 Bitmap 来表示每个用户对每篇文章的点赞状态,假设文章的 ID 是 articleId,用户的 ID 是 userId,可以使用 SETBIT 命令来设置用户对文章的点赞状态。

其中:article:{articleId}:likes 作为键,用户 ID 作为偏移量。

注意事项:这里用户ID必须是数字类型。

Step1、编写业务逻辑

@Service
public class ArticleService {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    private static final String LIKE_KEY_PREFIX = "article:%s:likes";

    // 点赞
    public void likeArticle(Long articleId, Long userId) {
        String key = String.format(LIKE_KEY_PREFIX, articleId);
        redisTemplate.opsForValue()
                .setBit(key, userId.intValue(), true);
    }

    // 取消点赞
    public void unlikeArticle(Long articleId, Long userId) {
        String key = String.format(LIKE_KEY_PREFIX, articleId);
        redisTemplate.opsForValue()
                .setBit(key, userId.intValue(), false);
    }

    // 获取点赞数量
    public Long getLikeCount(Long articleId) {
        String key = String.format(LIKE_KEY_PREFIX, articleId);
        Long bitCount = redisTemplate.execute((RedisCallback<Long>) connection ->
                connection.bitCount(key.getBytes()), true);
        return bitCount != null ? bitCount : 0;
    }

    // 检查用户是否点赞
    public boolean hasLiked(Long articleId, Long userId) {
        String key = String.format(LIKE_KEY_PREFIX, articleId);
        return Boolean.TRUE.equals(redisTemplate.opsForValue()
                .getBit(key, userId.intValue()));
    }
}

Step2、编写控制器

@RestController
@RequestMapping("/articles")
public class ArticleController {

    @Autowired
    private ArticleService articleService;

    /**
     * 用户点赞
     * @param articleId 文章ID
     * @param userId 用户ID
     */
    @PostMapping("/{articleId}/like/{userId}")
    public ResponseEntity<String> likeArticle(@PathVariable Long articleId, @PathVariable Long userId) {
        articleService.likeArticle(articleId, userId);
        return ResponseEntity.ok("OK");
    }

    /**
     * 用户取消点赞
     * @param articleId 文章ID
     * @param userId 用户ID
     */
    @PostMapping("/{articleId}/unlike/{userId}")
    public ResponseEntity<String> unlikeArticle(@PathVariable Long articleId, @PathVariable Long userId) {
        articleService.unlikeArticle(articleId, userId);
        return ResponseEntity.ok("OK");
    }

    /**
     * 获取某文章的点赞数量
     * @param articleId 文章ID
     */
    @GetMapping("/{articleId}/likes/count")
    public ResponseEntity<Long> getLikeCount(@PathVariable Long articleId) {
        Long count = articleService.getLikeCount(articleId);
        return ResponseEntity.ok(count);
    }

    /**
     * 判断用户是否点赞
     * @param articleId 文章ID
     * @param userId 用户ID
     */
    @GetMapping("/{articleId}/like/{userId}")
    public ResponseEntity<Boolean> hasLiked(@PathVariable Long articleId, @PathVariable Long userId) {
        boolean hasLiked = articleService.hasLiked(articleId, userId);
        return ResponseEntity.ok(hasLiked);
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2178693.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

设计效率拉高!一键生成国庆主题3d立体字!

​ 一键生成国庆主题字&#xff01;这是数字75&#xff0c;上传&#xff0c;点击生成 等个几秒&#xff0c;75周年立体字就做好了 而且融入了各种中国古建筑元素 这样的国庆主题字效果&#xff0c;以前我们要用c4d建模然后渲染出效果图 费时费力才做出一张 现在我们工作流…

事实与价值双阈值是算计启动的门槛

在现代社会&#xff0c;个体与群体的决策过程受到多种因素的影响&#xff0c;其中事实与价值的关系尤为重要。事实作为客观存在的基础&#xff0c;价值则是主观认知的体现。两者的相互作用构成了人类行为的复杂性&#xff0c;尤其在经济学、社会学以及伦理学等领域&#xff0c;…

JAVA毕业设计182—基于Java+Springboot+vue3的河道治理管理系统(源代码+数据库)

毕设所有选题&#xff1a; https://blog.csdn.net/2303_76227485/article/details/131104075 基于JavaSpringbootvue3的河道治理管理系统(源代码数据库)182 一、系统介绍 本项目前后端分离(可以改为ssm版本)&#xff0c;分为用户、工作人员、管理员三种角色 1、用户&#x…

linux 系统磁盘空间查看与清理

正常清理步骤 首先查看文件和目录的使用空间&#xff0c;系统/根目录下的文件夹一般情况不会占用大的磁盘空间&#xff0c;因此可主要查看您创建的目录或文件等 文件大小 使用ls -alh命令来查看&#xff0c;比如下方的.bashrc、.profile文件的大小。但是看到的文件夹大小仅仅…

Spire.PDF for .NET【页面设置】演示:设置 PDF 的查看器首选项和缩放系数

优化查看器首选项和缩放因子对于改善 PDF 文档的查看体验至关重要。通过使用适当的查看器首选项和缩放因子&#xff0c;您可以使您的 PDF 文档更加用户友好、可查看且适合不同的设备和平台。在本文中&#xff0c;我们将演示如何使用Spire.PDF for .NET在 C# 和 VB.NET 中为 PDF…

【计算机网络】详解HTTP请求和响应格式常见请求方法Header报头响应报文状态码URL

一、HTTP协议的定义 在互联网世界中&#xff0c;HTTP &#xff08;HyperText Transfer Protocol&#xff0c;超文本传输协议&#xff09;是一个至关重要的协议。它定义了客户端&#xff08;如浏览器&#xff09;与服务器之间如何通信&#xff0c;以交换或传输超文本&#xff08…

毕业设计选题:基于springboot+vue+uniapp的在线办公小程序

开发语言&#xff1a;Java框架&#xff1a;springbootuniappJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#…

召回11 地理位置召回、作者召回、缓存召回

有用但重要性不高 地理位置召回 GeoHash召回&#xff1a;对身边周围的事情感兴趣 GeoHash把经纬度编码成二进制哈希码方便检索。召回只根据经纬度这个地理位置&#xff0c;返回一批优质笔记&#xff0c;完全不考虑用户兴趣&#xff0c;也是因此返回优质笔记&#xff0c;大概…

[Docker学习笔记]Docker的原理Docker常见命令

文章目录 什么是DockerDocker的优势Docker的原理Docker 的安装Docker 的 namespaces Docker的常见命令docker version:查看版本信息docker info 查看docker详细信息我们关注的信息 docker search:镜像搜索docker pull:镜像拉取到本地docker push:推送本地镜像到镜像仓库docker …

安卓13设置删除网络和互联网选项 android13隐藏设置删除网络和互联网选项

总纲 android13 rom 开发总纲说明 文章目录 1.前言2.问题分析3.代码分析4.代码修改4.1修改方法14.2修改方法25.编译6.彩蛋1.前言 有些客户不想让用户修改默认的网络配置,禁止用户进入里面调整网络相关的配置。 2.问题分析 像这个问题,我们有好几种方法去处理,这种需求一般…

PyGWalker:让你的Pandas数据可视化更简单,快速创建数据可视化网站

1、PyGWalker应用: 在数据分析的过程中,数据的探索和可视化是至关重要的环节,如何高效地将分析结果展示给团队、客户,甚至是公众,是很多数据分析师和开发者面临的挑战,接下来介绍的两大工具组合——PyGWalker与Streamlit,可以帮助用户轻松解决这个问题,即使没有复杂的代…

java 洛谷题单【数据结构1-1】线性表

P3156 【深基15.例1】询问学号 解题思路 很简单的一道题&#xff0c;但是由于n、m的数据很大&#xff0c;要用Java的I/O流读入和输出。 import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.StreamTokenizer; impo…

【springboot】使用thymeleaf模板

1. 导入依赖 首先&#xff0c;创建一个Spring Boot项目&#xff0c;并添加Thymeleaf依赖。在pom.xml文件中添加以下依赖&#xff1a; <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifa…

9.28 daimayuan 模拟赛总结

感觉 -S 模拟赛时间好紧啊 复盘 8:00 开题 扫了一遍四道题&#xff0c;感觉 T1 很典&#xff0c;T2 有点神秘&#xff0c;T3 计数&#xff0c;但限制是简单的&#xff0c;看上去非常可做&#xff1b;T4 也有点神秘 推 T1&#xff0c;先定根&#xff0c;然后树形dp是显然的&…

【Android】Jetpack组件之LifeCycle

引言 Lifecycle组件是Android Jetpack架构组件之一&#xff0c;它提供了一种方法来管理Android组件&#xff08;如Activity、Fragment和服务&#xff09;的生命周期。Lifecycle组件帮助你执行与生命周期相关联的操作&#xff0c;确保在适当的时间发生适当的事情&#xff0c;例…

服务器几核几G几M是什么意思?如何选择?

服务器几核几G几M是什么意思&#xff1f;我们建站、搭建网络平台都要用到云服务器&#xff0c;不管在腾讯云、阿里云还是别的云服务平台选购&#xff0c;都会接触到服务器配置。云服务器就是把物理服务器&#xff08;俗称“母鸡”&#xff09;&#xff0c;用虚拟机技术虚拟出多…

LeetCode: 1971. 寻找图中是否存在路径

寻找图中是否存在路径 原题 有一个具有 n 个顶点的 双向 图&#xff0c;其中每个顶点标记从 0 到 n - 1&#xff08;包含 0 和 n - 1&#xff09;。图中的边用一个二维整数数组 edges 表示&#xff0c;其中 edges[i] [ui, vi] 表示顶点 ui 和顶点 vi 之间的双向边。 每个顶点…

mips指令系统简介

**MIPS&#xff08;Microprocessor without Interlocked Piped Stages&#xff09;**&#xff1a;这是一种RISC&#xff08;精简指令集计算&#xff09;芯片架构&#xff0c;由John L. Hennessy设计&#xff0c;特点是没有内部互锁的流水级&#xff0c;简化了处理器设计。 对比…

python Scrapy 框架断点设置

文章目录 前言python Scrapy 框架断点设置1. 常用的 pdb 调试命令2. 示例流程 前言 如果您觉得有用的话&#xff0c;记得给博主点个赞&#xff0c;评论&#xff0c;收藏一键三连啊&#xff0c;写作不易啊^ _ ^。   而且听说点赞的人每天的运气都不会太差&#xff0c;实在白嫖…

等保2.0数据库测评之优炫数据库测评

一、优炫数据库介绍 优炫数据库系统主要包含&#xff1a;优炫数据库&#xff08;以下简称UXDB&#xff09;、优炫数据库管理平台&#xff08;以下简称 UXDBWeb&#xff09;和优炫数据库图形化开发软件&#xff08;以下简称UXDBAdmin&#xff09;。UXDB是一款数据库软件&#x…