Redis常用扩展数据类型(BitSet、HyperLogLog、GEO)

BitSet/HyperLogLog

聚合统计

建议使用Set类型,但是以下命令时间复杂度均为O(N),数据量大时可能会有阻塞问题。

以user:id存储的用户id数据为例。

交集

统计8月4日相对于8月3日留存的用户。

SINTERSTORE user:id:rem user:id:20200803 user:id:20200804

并集

统计所有用户,将8月4日的用户并入总用户中。

SUNIONSTORE user:id user:id user:id:20200803

差集

统计8月4日新增用户。

SDIFFSTORE user:new user:id:20200804 user:id

排序统计

建议使用Sorted List或List。

面对稳定不变的数据,可以考虑使用List通过下标直接分页。插入数据会导致下标变化,分页可能会显示重复数据。

面对评论或者首页等频繁更新数据的场景,建议使用Sorted List,由于分数固定,通过ZRANGEBYSCORE命令可以避免分页期间的数据插入问题。

二值状态统计

集合状态只有0和1,常用于签到、心跳等统计。

建议使用Bitmap。底层实现为String类型,因为String类型是保存形式为二进制的字节数组。

统计某用户的月度签到或者年度签到情况,可以用31位或者365位的Bitmap即可。

  • SETBIT {key} {index}

    SETBIT uid:sign:3000:202008 2 1,表示用户id为3000的用户在20年8月3日已签到

  • GETBIT {key}

    GETBIT uid:sign:3000:202008 2

  • BITCOUNT

    BITCOUNT uid:sign:3000:202008

基数统计

需要统计的数据量很大时,建议HyperLogLog类型。
HyperLogLog计算基数所需的空间总是固定的12 KB,便可以计算接近 2^64 个元素的基数。
但是HyperLogLog的统计规则是基于概率完成的,所以它给出的统计结果是有一定误差的,标准误算率是 0.81%。

HyperLogLog 是一种用于大数据量下统计基数的算法。它的基本原理如下:
  初始化:创建一个位数组(bit array),数组的长度由用户指定。初始时,数组的所有位都设置为0。
  哈希映射:对每个输入元素进行哈希运算,将其映射到一个二进制字符串。这个哈希函数应该是均匀的,即不同输入元素的哈希值分布应该是随机的。
  统计前导零位(Leading Zeros):对每个哈希值,从左往右数,找到第一个为0的位置,记录其位置的索引(即前导零位的数量)。
  更新位数组:对于每个哈希值,根据前导零位的索引更新位数组中相应位置的值。如果新的前导零位数量大于当前位数组中的值,那么更新该位置。
  估算基数:对位数组进行处理,计算估算的基数。位数组中的每个位置对应于输入元素的哈希值,通过比较前导零位的数量,可以大致估计出基数的大小。当位数组的长度较大时,能够提供较准确的基数估计。误差范围通常在2%左右,但具体的误差受到位数组长度的影响。
PFADD page1:uv user1 user2 user3 user4 user5
PFCOUNT page1:uv

位置信息服务

LBS(Location-Based Service)应用:数据是和人或物关联的一组经纬度信息,切能查询相邻的经纬度范围。

建议使用GEO类型,底层实现为Sorted Set。查询相邻的经纬度范围利用Score分数来来支撑,通过GeoHash编码将经纬度转为浮点数。

GeoHash编码

原理

首先先对经度和纬度分别编码,然后再把经纬度各自的编码组合成一个最终编码。

基本原理: 二分区间,区间编码

如针对精度值116.37的编码过程,将所在区间不断二分N次,并通过0或1表示在区间左或右。
N为9的时候误差为4米,N为10的时候误差为0.6米。当前N为5。

对纬度的编码同上规则。如纬度值为39.86编码过程如下。

组合编码:最终编码值的偶数位上依次是经度的编码值,奇数位上依次是纬度的编码值,其中,偶数位从0开始,奇数位从1开始。

交替组合的原因是为了让经纬度接近的位置生成的数值权重接近,便于Sorted Set中的Score排序范围查询。

组合编码结果例子如下。

缺点

GeoHash编码将经纬度画分成了N*N的方格,但是有的编码值虽然在大小上接近,但实际对应的方格却距离比较远。如图所示。

命令

假设车辆 ID 是 33,经纬度位置是(116.034579,39.030452),用GEO 集合保存所有车辆的经纬度,集合key是cars:locations。

GEOADD cars:locations 116.034579 39.030452 33

根据经纬度信息(116.054579,39.030452 ),查找以这个经纬度为中心的 5 公里内的车辆信息.

GEORADIUS cars:locations 116.054579 39.030452 5 km ASC COUNT 10

posted @ 2023-11-10 17:26  kiper  阅读(63)  评论(0编辑  收藏  举报