【Redis扩展】Redis两种高级数据结构-HyperLogLog、BitMap

news2024/11/14 20:27:24

一、HyperLoglog-基数统计

1. HyperlogLog数据类型特点

  • Redis HyperLogLog 是用来做基数统计的算法,用以完成独立总数的统计
  • HyperLogLog 的优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定的、并且是很小的。花费 12 KB 内存,就可以计算接近 2^64 个不同元素的基数。
  • 因为 HyperLogLog 只会根据输入元素来计算基数,而不会储存输入元素本身,所以 HyperLogLog 不能像集合那样,返回输入的各个元素。
  • 其底层使用string数据类型
  • 其是不精确的统计算法,标准误差为0.81%

什么是基数
数据集中不重复的元素的个数。

2. 应用场景

  • 网页的访问量(UV):一个用户多次访问,也只能算作一个人。
    传统实现,存储用户的id,然后每次进行比较。当用户变多之后这种方式及其浪费空间,而我们的目的只是计数,Hyperloglog就能帮助我们利用最小的空间完成。

  • 即如果允许容错或对精度要求没有这么高,那么一定可以使用Hyperloglog !

  • 如果不允许容错,就使用set或者自己的数据类型即可 !

3. 常用API及使用Spring客户端测试

redis原生API

命令描述
pfadd key element1 [elememt2…]添加指定元素到 HyperLogLog 中
pfcount key [key]返回给定 HyperLogLog 的基数估算值。
pfmerge mergekey sourcekey [sourcekey…]将多个 HyperLogLog 合并为一个 HyperLogLog
# 添加元素和统计个数
127.0.0.1:6379> PFADD myelemx a b c d e f g h i j k # 添加元素
(integer) 1
127.0.0.1:6379> type myelemx # hyperloglog底层使用String
string
127.0.0.1:6379> PFCOUNT myelemx # 估算myelemx的基数
(integer) 11
127.0.0.1:6379> PFADD myelemy i j k z m c b v p q s
(integer) 1
127.0.0.1:6379> PFCOUNT myelemy
(integer) 11

# 合并
127.0.0.1:6379> PFMERGE myelemz myelemx myelemy # 合并myelemx和myelemy 成为myelemz
OK
127.0.0.1:6379> PFCOUNT myelemz # 估算基数
(integer) 17

Spring客户端操作API

opsForHyperLogLog().add(pfKey, i)-添加数据

opsForHyperLogLog().size(pfKey)-统计数据的基数

/**
 * 测试对HyperlogLog的操作
 */
@Test
public void testHyperLogLog() 
    // 添加100 00个不重复的数、100 00个重复的数-共20万个数
    String pfKey = "test:hll:01";
    for (int i = 0; i < 10000; i++) {
        redisTemplate.opsForHyperLogLog().add(pfKey, i);
    }
    for (int i = 0; i < 10000; i++) {
        int r = (int)(Math.random() * 10000);
        redisTemplate.opsForHyperLogLog().add(pfKey, r);
    }
    // 统计指定key中所有不重复的基数个数
    long size = redisTemplate.opsForHyperLogLog().size(pfKey);
    System.out.println(size);
}

opsForHyperLogLog().union(unionKey, pfKey2, pfKey3, pfKey4) 将pfKey2, pfKey3, pfKey4的数合并到unionKey中

/**
 * 合并数据-并统计合并后的基数
 */
@Test
public void testHyperLogLogUnion() {
    String pfKey2 = "test:hll:02";
    String pfKey3 = "test:hll:03";
    String pfKey4 = "test:hll:04";
    for (int i = 0; i < 10000; i++) {
        redisTemplate.opsForHyperLogLog().add(pfKey2, i);
    }
    for (int i = 5000; i < 15000; i++) {
        redisTemplate.opsForHyperLogLog().add(pfKey3, i);
    }
    for (int i = 10000; i < 20000; i++) {
        redisTemplate.opsForHyperLogLog().add(pfKey4, i);
    }
    // 合并三组数
    String unionKey = "test:hll:union";
    redisTemplate.opsForHyperLogLog().union(unionKey, pfKey2, pfKey3, pfKey4);

    // 统计合并后的基数
    long size = redisTemplate.opsForHyperLogLog().size(unionKey);
    System.out.println(size);
}

二、BitMap-位图

1. BitMap数据结构特点

  • 使用位存储,信息状态只有 0 和 1
    • 可以将其看作Byte数组
    • 可以储存大量连续数据的布尔值

2. 应用场景

  • 签到统计、状态统计

统计用户信息,活跃,不活跃! 登录 、 未登录! 打卡,365打卡! 两个状态的,都可以使用
Bitmaps!

3. 常用API及Spring客户端测试

redis原生API

命令描述
setbit key offset value为指定key的offset位设置值
getbit key offset获取offset位的值
bitcount key [start end]统计字符串被设置为1的bit数,也可以指定统计范围按字节
bitop operration destkey key[key…]对一个或多个保存二进制位的字符串 key 进行位元操作,并将结果保存到 destkey 上。
BITPOS key bit [start] [end]返回字符串里面第一个被设置为1或者0的bit位。start和end只能按字节,不能按位
# 添加数据和获取数据
127.0.0.1:6379> setbit sign 0 1 # 设置sign的第0位为 1 
(integer) 0
127.0.0.1:6379> setbit sign 2 1 # 设置sign的第2位为 1  不设置默认 是0
(integer) 0
127.0.0.1:6379> setbit sign 3 1
(integer) 0
127.0.0.1:6379> setbit sign 5 1
(integer) 0
127.0.0.1:6379> type sign	# 底层也是String类型
string

127.0.0.1:6379> getbit sign 2 # 获取第2位的数值
(integer) 1
127.0.0.1:6379> getbit sign 3
(integer) 1
127.0.0.1:6379> getbit sign 4 # 未设置默认是0-及false
(integer) 0

# 统计数据中为1的个数-即为true的个数
127.0.0.1:6379> BITCOUNT sign # 统计sign中为1的位数
(integer) 4

spring客户端操作API

  • opsForValue().setBit(bitKey, 1, true)- 设置状态
    默认每位的状态为false
  • opsForValue().getBit(bitKey, 0))- 查询状态
  • redisConnection.bitCount(bitKey.getBytes())- 统计状态为true的个数
/**
 * 测试对BitMaps的操作
 * 记录-查询和统计
 */
@Test
public void testBitMap() {
    String bitKey = "test:bit:01";
    // 记录数据状态-默认false
    redisTemplate.opsForValue().setBit(bitKey, 1, true);
    redisTemplate.opsForValue().setBit(bitKey, 4, true);
    redisTemplate.opsForValue().setBit(bitKey, 7, true);

    // 查询
    System.out.println(redisTemplate.opsForValue().getBit(bitKey, 0));
    System.out.println(redisTemplate.opsForValue().getBit(bitKey, 1));
    System.out.println(redisTemplate.opsForValue().getBit(bitKey, 2));

    // 统计
    Object execute = redisTemplate.execute(new RedisCallback() {
        @Override
        public Object doInRedis(RedisConnection redisConnection) throws DataAccessException {
            return redisConnection.bitCount(bitKey.getBytes());
        }
    });

    System.out.println(execute);
}

connection.bitOp()- 位运算

/**
 * OR运算
 * 统计3组数据的布尔值, 并对这3组数据做OR运算.
 */
@Test
public void testBitMapOperation() {
    String bitKey2 = "test:bm:02";
    redisTemplate.opsForValue().setBit(bitKey2, 0, true);
    redisTemplate.opsForValue().setBit(bitKey2, 1, true);
    redisTemplate.opsForValue().setBit(bitKey2, 2, true);

    String bitKey3 = "test:bm:03";
    redisTemplate.opsForValue().setBit(bitKey3, 2, true);
    redisTemplate.opsForValue().setBit(bitKey3, 3, true);
    redisTemplate.opsForValue().setBit(bitKey3, 4, true);

    String bitKey4 = "test:bm:04";
    redisTemplate.opsForValue().setBit(bitKey4, 4, true);
    redisTemplate.opsForValue().setBit(bitKey4, 5, true);
    redisTemplate.opsForValue().setBit(bitKey4, 6, true);

    // 合并处理
    String bitKeyOR = "test:bm:or";
    Object obj = redisTemplate.execute(new RedisCallback() {
        @Override
        public Object doInRedis(RedisConnection connection) throws DataAccessException {
            connection.bitOp(RedisStringCommands.BitOperation.OR,
                    bitKeyOR.getBytes(), bitKey2.getBytes(), bitKey3.getBytes(), bitKey4.getBytes());
            return connection.bitCount(bitKeyOR.getBytes());
        }
    });

    System.out.println(obj);    // 统计的个数

    // 合并后,每位的状态
    System.out.println(redisTemplate.opsForValue().getBit(bitKeyOR, 0));
    System.out.println(redisTemplate.opsForValue().getBit(bitKeyOR, 1));
    System.out.println(redisTemplate.opsForValue().getBit(bitKeyOR, 2));
    System.out.println(redisTemplate.opsForValue().getBit(bitKeyOR, 3));
    System.out.println(redisTemplate.opsForValue().getBit(bitKeyOR, 4));
    System.out.println(redisTemplate.opsForValue().getBit(bitKeyOR, 5));
    System.out.println(redisTemplate.opsForValue().getBit(bitKeyOR, 6));
}

在这里插入图片描述

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

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

相关文章

springboot整合邮箱功能二(实战)

【SpringBoot整合Email发送邮件】_ζั͡ ั͡空 ั͡ ั͡白&#xfffd;的博客-CSDN博客 https://www.cnblogs.com/erlou96/p/16878192.html#_label1_5 1. 准备工作 1.1 qq邮箱设置 本文默认使用qq邮箱来发送邮件,然后使用一个在线临时邮箱来接收邮件。为了让程序能够通过…

Semantic Segmentation using Adversarial Networks代码

代码来源 首先看一下模型架构&#xff1a; 损失计算&#xff1a; class GANUpdater(chainer.training.StandardUpdater, UpdaterMixin):def __init__(self, *args, **kwargs):self.model kwargs.pop(model) # set for exeptions.Evaluatorself.gen, self.dis self.model[g…

O2OA中如何使用PostgreSQL + Citus 实现分布式数据库实现方案?

虽然 O2OA 数据表高效的表结构以及索引的设计已经极大程度地保障了数据存取操作的性能&#xff0c;但是随着使用时间从增长&#xff0c;数据表存放的数据量也会急剧增长。此时&#xff0c;仍然需要有合适的方案来解决数据量产生的系统性能瓶颈。本文介绍通过 PostgreSQL Citus…

2023年5月DAMA-CDGA/CDGP数据治理认证开班啦,我要报名学习

6月18日DAMA-CDGA/CDGP数据治理认证考试开放报名中&#xff01; 考试开放地区&#xff1a;北京、上海、广州、深圳、长沙、呼和浩特、杭州、南京、济南、成都、西安。其他地区凑人数中… DAMA-CDGA/CDGP数据治理认证班进行中&#xff0c;报名从速&#xff01; DAMA认证为数据…

【刷题之路】LeetCode 234. 回文链表

【刷题之路】LeetCode 234. 回文链表 一、题目描述二、解题1、方法1——复制值到数组后用双指针1.1、思路分析1.2、代码实现 2、方法2——反转另一半链表2.1、思路分析2.2、代码实现2.3、补充 3、方法3——递归3.1、思路分析3.2、代码实现 一、题目描述 原题连接&#xff1a; …

计算机图形学 | 裁剪与屏幕映射

计算机图形学 | 裁剪与屏幕映射 计算机图形学 | 裁剪与屏幕映射8.1 裁剪思想裁剪的概念编码裁剪法中点裁剪法Liang-Barsky算法 8.2 真正的裁剪——在三维空间遇见多边形真正的裁剪多边形的裁剪Weiler-Atherton算法三维空间中的裁剪 8.3 几何阶段的完结&#xff1a;屏幕映射屏幕…

API 接口的使用和功能

随着互联网的快速发展&#xff0c;API接口已经成为了现代开发中不可或缺的一部分。API接口可以让你的应用程序与其他应用程序、系统或服务进行数据交流和集成。如果你正在开发应用程序&#xff0c;那么最好的方法就是使用API接口来增强功能和性能。 我们的API接口是为您的应用…

上财黄烨:金融科技人才的吸引与培养

“金融科技企业在吸引人才前&#xff0c;应先完善人才培养机制&#xff0c;建立员工画像&#xff0c;有针对性地培训提高成员综合素质。” ——上海金融智能工程技术研究中心上海财经大学金融科技研究院秘书长&院长助理黄烨老师 01.何为数字人才&#xff1f; 目前大多数研…

什么,你不会Windows本地账户和本地组账户的管理加固?没意思

什么&#xff0c;你不会Windows本地账户和本地组账户的管理加固&#xff1f;没意思 1.图形化界面方式管理用户2.图形化界面方式管理用户组3.命令行界面方式管理用户4.命令行界面方式管理账户组5.账户安全基线加固账户检查口令检查 1.图形化界面方式管理用户 1、打开管理界面 …

运维自动化工具 Ansible的安装部署和常用模块介绍

ansible安装 ansible的安装有很多种方式 官方文档&#xff1a;https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.ht ml https://docs.ansible.com/ansible/latest/installation_guide/index.html 下载 https://releases.ansible.com/ansible…

Java入门全网最详细 - 从入门到转行

Java基础入门 - 坚持 Java 基本介绍Java 学习须知Java 学习文档Java 基础Java Hello WorldJava 变量Java 数据类型Java 运算符Java 修饰符Java 表达式 & 语句 & 代码块Java 注释--------------------------------------------------------------------------Java 控制语…

在vue中引入高德地图

既然要用到高德地图首先要申请成为高德地图开发者&#xff0c;并申请使用高德地图的key这两点在这篇文章就不过多赘述&#xff0c;有需要的小伙伴可以查查资料&#xff0c;或者去高德地图api官网都有很详细的介绍。高德地图官网 简单提一下申请秘钥流程&#xff08;web端&#…

Python入门教程+项目实战-12.2节: 字典的操作方法

目录 12.2.1 字典的常用操作方法 12.2.2 字典的查找 12.2.3 字典的修改 12.2.4 字典的添加 12.2.5 字典的删除 12.2.6 知识要点 12.2.7 系统学习python 12.2.1 字典的常用操作方法 字典类型是一种抽象数据类型&#xff0c;抽象数据类型定义了数据类型的操作方法&#x…

想成为神经网络大师?这些常用算法和框架必须掌握!

神经网络是机器学习和人工智能领域中的一种常用算法&#xff0c;它在图像识别、自然语言处理等方面都有广泛的应用。如果你想入门神经网络&#xff0c;那么这篇文章就是为你准备的。 首先&#xff0c;了解基本概念是入门神经网络的基础。神经元是神经网络的基本组成部分&#x…

AQS底层源码解析

可重入锁 又叫递归锁&#xff0c;同一个线程在外层方法获得锁的时候&#xff0c;再进入该线程内层方法会自动获取锁&#xff0c;&#xff08;前提锁对象是同一个对象&#xff09;。不会因为之前已经获取过还没释放而阻塞。 Synchronized和ReentrantLock都是可重入锁&#xff…

玩游戏时突然弹出”显示器驱动程序已停止响应并且已恢复”怎么办

随着3A游戏大作不断面市&#xff0c;用户也不断地提升着自己的硬件设备。但是硬件更上了&#xff0c;却还会出现一些突如其来的情况&#xff0c;比如正准备开启某款游戏时&#xff0c;电脑右下角突然出现“显示器驱动程序已停止响应并且已恢复”。遇事不慌&#xff0c;驱动人生…

创新指南|5大策略让创新业务扩张最大避免“增长痛苦”

公司在开发和孵化新业务计划方面进行了大量投资&#xff0c;但很少有公司遵循严格的途径来扩大新业务规模。虽然80%的公司声称构思和孵化新企业&#xff0c;但只有16%的公司成功扩大了规模。典型案例是百思买在许多失败倒闭的扩大新业务取得了成功。它经历了建立新业务所需的3个…

如何使用 Python+selenium 进行 web 自动化测试?

使用Pythonselenium进行web自动化测试主要分为以下步骤&#xff1a; 在华为工作了10年的大佬出的Web自动化测试教程&#xff0c;华为现用技术教程&#xff01;_哔哩哔哩_bilibili在华为工作了10年的大佬出的Web自动化测试教程&#xff0c;华为现用技术教程&#xff01;共计16条…

VMware ESXi 7.0 U3m macOS Unlocker OEM BIOS (标准版和厂商定制版)

VMware ESXi 7.0 U3m macOS Unlocker & OEM BIOS (标准版和厂商定制版) 提供标准版和 Dell (戴尔)、HPE (慧与)、Lenovo (联想)、Inspur (浪潮)、Cisco (思科) 定制版镜像 请访问原文链接&#xff1a;https://sysin.org/blog/vmware-esxi-7-u3-oem/&#xff0c;查看最新版…

AC/DC、DC/DC转换器

什么是AC&#xff1f; Alternating Current&#xff08;交流&#xff09;的首字母缩写。 AC是大小和极性&#xff08;方向&#xff09;随时间呈周期性变化的电流。 电流极性在1秒内的变化次数被称为频率&#xff0c;以Hz为单位表示。 什么是DC&#xff1f; Direct Current&…