• Redis 中新的三种数据类型


    4、Redis 新的三种数据类型

    4.1、Bitmaps 位操作字符串

    4.1.1、简介

    现代计算机使用二进制(位)作为信息的基本单位,1个字节等于8位,例如“abc”字符串是有3个字节组成,但实际在计算机内存储时将其使用二进制表示,“abc”分别对应的ASCII码是:97、98、99,对应的二进制分别是 01100001、01100010、01100011,如下图

    在这里插入图片描述

    合理地使用位操作能够有效地提高内存使用率和开发效率。

    Redis 提供了 Bitmaps 这个“数据类型”可以实现对位的操作:

    • Bitmaps 本身不是一种数据类型, 实际上它就是字符串(key-value) , 但是它可以对字符串的位进行操作,字符串中每个字符对应 1 个字节,也就是 8 位,一个字符可以存储 8 个 bit 位信息。

    • Bitmaps 单独提供了一套命令, 所以在 Redis 中使用 Bitmaps 和使用字符串的方法不太相同。 可以把 Bitmaps 想象成一个以位为单位的数组, 数组的每个单元只能存储 0 和 1 , 数组的下标在 Bitmaps 中叫做偏移量。

    在这里插入图片描述


    4.1.2、常用命令

    操作作用
    setbit设置某个偏移量的值
    getbit返回某个偏移量的值
    bitcount返回指定范围 bit 位都为 1 的数量
    bittop对一个或多个 bitmaps 执行位操作
    setbit 设置某个偏移量的值
    127.0.0.1:6379> setbit key offset value
    
    • 1

    设置 offset 偏移位的值为 value,offset 的值是从 0 开始的,n 代表第 n+1 个 bit 位置的。

    offset 参数必须大于或等于 0 ,小于 2^32 (bit 映射被限制在 512 MB 之内)。

    value 的值只能为 0 或 1

    **返回值:**指定偏移量原来储存的位。

    注:bit 默认被初始化为 1;

    getbit 返回某个偏移量的值
    127.0.0.1:6379> getbit key offset
    
    • 1
    bitcount 返回指定范围 bit 位都为 1 的数量
    127.0.0.1:6379> bitcount key [start] [end]
    
    • 1

    统计字符串被设置为 1 的 bit 数,一般情况下,给定的整个字符串都会被进行统计,通过指定额外的 start 或者 end 参数,可以让计数只在特定的位上进行,start 和 end 参数,都可以使用负数值:比如 -1 表示最后一个位,而 -2 表示倒数第二个位,以此类推。
    注意了:start、end 是指 bit 组的字节的下标数,一个直接对应 8 个 bit,所以 [a,b] 对应的 offset 范围是[8a,8b+7]

    bitop 对一个或多个 bitmaps 执行位操作
    127.0.0.1:6379> bitop operation destkey key [key ...]
    
    • 1

    对一个或多个保存二进制位的字符串 key 进行位元操作,并将结果保存到 destkey 上。

    operation 可以是 AND 、 OR 、 NOT 、 XOR 这四种操作中的任意一种:

    • bitop and destkey key [key …] ,对一个或多个 key 求逻辑并,并将结果保存到 destkey;

    • bitop or destkey key [key …] ,对一个或多个 key 求逻辑或,并将结果保存到 destkey;

    • bitop xor destkey key [key …] ,对一个或多个 key 求逻辑异或,并将结果保存到 destkey;

    • bitop not destkey key ,对给定 key 求逻辑非,并将结果保存到 destkey;

    除了 not 操作之外,其他操作都可以接受一个或多个 key 作为输入。

    **返回值:**保存到 destkey 的字符串的长度,和输入 key 中最长的字符串长度相等。


    4.1.3、Bitmaps 与 Set 比较

    假设网站有 1 亿用户, 每天独立访问的用户有 5 千万, 如果每天用集合类型和 Bitmaps 分别存储活跃用户可以得到表:

    set 和 Bitmaps 存储一天活跃用户对比:

    数据类型每个用户 id 占用空间需要存储的用户量全部内存量
    set集合64 位5000000064 位 * 50000000 = 400MB
    Bitmaps1位1000000001 位 * 100000000 = 12.5MB

    很明显, 这种情况下使用 Bitmaps 能节省很多的内存空间, 尤其是随着时间推移节省的内存还是非常可观的。

    set 和 Bitmaps 存储独立用户空间对比:

    数据类型一天一月一年
    set集合400MB12GB144GB
    Bitmaps12.5MB375MB4.5GB

    但 Bitmaps 并不是万金油, 假如该网站每天的独立访问用户很少, 例如只有 10 万(大量的僵尸用户), 那么两者的对比如下表所示, 很显然, 这时候使用 Bitmaps 就不太合适了, 因为基本上大部分位都是 0。

    数据类型每个 userid 占用空间需要存储的用户量全部内存量
    集合64 位10000064 位 * 100000 = 800KB
    Bitmaps1 位1000000001 位 * 100000000 = 12.5MB

    4.2、HyperLogLog

    4.2.1、简介

    在工作当中,我们经常会遇到与统计相关的功能需求,比如统计网站PV(PageView页面访问量),可以使用 Redis 的 incr、incrby 轻松实现。

    但像 UV(UniqueVisitor,独立访客)、独立 IP 数、搜索记录数等需要去重和计数的问题如何解决?这种求集合中不重复元素个数的问题称为基数问题。

    解决基数问题有很多种方案:

    (1)数据存储在MySQL表中,使用 distinct count 计算不重复个数

    (2)使用 Redis 提供的 hash、set、bitmaps 等数据结构来处理

    以上的方案结果精确,但随着数据不断增加,导致占用空间越来越大,对于非常大的数据集是不切实际的。

    能否能够降低一定的精度来平衡存储空间?Redis推出了 HyperLogLog

    Redis HyperLogLog 是用来做基数统计的算法,HyperLogLog 的优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定的、并且是很小的。

    在 Redis 里面,每个 HyperLogLog 键只需要花费 12 KB 内存,就可以计算接近 2^64 个不同元素的基数。这和计算基数时,元素越多耗费内存就越多的集合形成鲜明对比。

    但是,因为 HyperLogLog 只会根据输入元素来计算基数,而不会储存输入元素本身,所以 HyperLogLog 不能像集合那样,返回输入的各个元素。

    什么是基数?

    比如数据集 {1, 3, 5, 7, 5, 7, 8}, 那么这个数据集的基数集为 {1, 3, 5 ,7, 8}, 基数(不重复元素)为5。 基数估计就是在误差可接受的范围内,快速计算基数。


    4.2.1、常用命令

    操作作用
    pfadd添加多个元素
    pfcount返回多个 HLL 合并后元素的个数
    pfmerge将多个 HLL 合并后元素放入另外一个 HLL
    pfadd 添加多个元素
    127.0.0.1:6379> pfadd key element [element ...]
    
    • 1

    向HyperLoglog类型的key中添加一个或者多个元素。

    添加一个或者多个元素到key对应的集合中。

    返回值:

    1:添加成功

    0:添加失败(元素已存在)

    pfcount 返回多个 HLL 合并后元素的个数
    127.0.0.1:6379> pfcount key1 key2 ...
    
    • 1
    pfmerge 将多个 HLL 合并后元素放入另外一个 HLL
    127.0.0.1:6379> pfmerge destkey sourcekey [sourcekey ...]
    
    • 1

    4.3、Geographic

    4.3.1、简介

    Reids3.2 中增加了对GEO类型的支持,GEO(Geographic),地理信息的缩写。

    该类型,就是元素的 2 维坐标,在地图上就是经纬度,redis基于该类型,提供了经纬度设置、查询、范围查询、距离查询,经纬度Hash等常见操作。


    4.3.2、常用命令

    操作作用
    geoadd添加多个位置的经纬度
    geopos添加多个位置的经纬度
    geodist获取两个位置的直线距离
    georadius以给定的经纬度为中心,找出某一半径内的元素
    geoadd 添加多个位置的经纬度
    # longitude latitude member:经度 维度 名称
    127.0.0.1:6379> geoadd key longitude latitude member [longitude latitude member ...]
    
    • 1
    • 2

    两级无法直接添加,一般会下载城市数据,直接通过java程序一次性导入。

    有效的经纬度从-180度到180度,有效的维度从-85.05112878度到85.05112878度。

    当坐标位置超出指定范围时,该命令将会返回一个错误。

    已经添加的数据,是无法再次往里面添加的。

    geopos 获取多个位置的坐标值
    # 无数据则,返回 null
    127.0.0.1:6379> geopos key member [member ...]
    
    • 1
    • 2
    geodist 获取两个位置的直线距离
    # 单位:[m|km|ft|mi] -> [米|千米|英里|英尺],默认为米
    127.0.0.1:6379> geodist key member1 member2 [m|km|ft|mi]
    
    • 1
    • 2
    georadius 以给定的经纬度为中心,找出某一半径内的元素
    127.0.0.1:6379> georadius key longitude latitude radius m|km|ft|mi
    
    • 1

    longitude latitude radius:经度 维度 半径

    单位:[m|km|ft|mi] -> [米|千米|英里|英尺],默认为米

  • 相关阅读:
    新版edge浏览器读取谷歌浏览器上的历史记录
    NX二次开发-C#多线程技术做exe外部开发(批量导出PDF图纸例子)
    钉钉与实在智能达成战略合作,实在Agent助力钉钉AI助理成为“新质生产力”
    亚信笔试题【带答案】
    【大数据折腾不息系列】(三) MySQL安装
    Linux--信号
    基于springboot实现滴答拍摄影项目【项目源码+论文说明】计算机毕业设计
    【Paper Note】利用Boundary-aware Attention边界感知注意力机制增强部分伪造音频定位
    性能测试流程注意事项(亲身经历希望能帮助到你)
    mybatis-plus 3.5.2 自动生成代码
  • 原文地址:https://blog.csdn.net/qq_44704799/article/details/126589204