Redis新数据类型 - Bitmap、HyperLogLog、Geospatial


🌈 个人主页: Hygge_Code
🔥 热门专栏:从0开始学习Java | Linux学习| 计算机网络
💫 个人格言: "既然选择了远方,便不顾风雨兼程"

文章目录

  • Redis新数据类型
    • 一、Bitmap(位图)
      • [1. 什么是Bitmap?](#1. 什么是Bitmap?)
      • [2. 核心应用场景](#2. 核心应用场景)
      • [3. 核心设计思路对比](#3. 核心设计思路对比)
      • [4. 核心命令](#4. 核心命令)
    • 二、HyperLogLog(基数统计)
      • [1. 什么是基数统计?](#1. 什么是基数统计?)
      • [2. 核心优势](#2. 核心优势)
      • [3. 核心应用场景](#3. 核心应用场景)
      • [4. 注意事项](#4. 注意事项)
      • [5. 核心命令](#5. 核心命令)
    • 三、Geospatial(地理空间)
      • [1. 什么是Geospatial?](#1. 什么是Geospatial?)
      • [2. 核心应用场景](#2. 核心应用场景)
      • [3. 核心限制](#3. 核心限制)
      • [4. 核心命令](#4. 核心命令)

Redis新数据类型

在Redis的基础数据类型(String、List、Set、Hash、Zset)之外,Redis还提供了几种轻量化、高性能的特殊数据类型,分别是Bitmap(位图)、HyperLogLog、Geospatial(地理空间)。

一、Bitmap(位图)

1. 什么是Bitmap?

Bitmap本质上是基于Redis的String类型实现的扩展,它将String的每个字节拆分为8个二进制位(bit),通过操作这些bit位(0/1)来表示业务状态。

一个String类型最大支持512M,换算成bit位就是 2^32个bit ,足以应对海量的状态存储场景。Bitmap的核心优势是极致的内存利用率,比如存储1000万条状态数据,仅需约1.2MB内存,远低于传统的String/Hash存储。

2. 核心应用场景

Bitmap的核心是二值状态统计,适合所有需要用"是/否""有/无"表示状态的场景,典型案例:

  • 用户签到统计(今日是否签到)
  • 网站UV统计(某用户今日是否访问)
  • 功能开关(某用户是否开启某功能)
  • 打卡记录(某员工是否打卡)

3. 核心设计思路对比

传统实现签到功能需要建签到表 ,每条签到记录占数十字节(用户姓名、签到日期、是否补签等等),1000万用户每年签到数据约占数GB ;而用Bitmap实现,仅需约几十MB,内存占用差距天壤之别。

4. 核心命令

Bitmap的所有命令均以BIT开头,核心命令及实操示例如下:

命令 作用 示例
SETBIT key offset value 给指定偏移量设置0/1(offset从0开始) SETBIT sign:1001:202510 0 1(用户1001 10月1日签到) SETBIT sign:1001:202510 1 1(用户1001 10月2日签到) SETBIT sign:1001:202510 3 1(用户1001 10月4日签到)
GETBIT key offset 查询指定偏移量的bit值 GETBIT sign:1001:202510 20(10月3日未签到)
BITCOUNT key [start end] 统计key中值为1的bit位数量 BITCOUNT sign:1001:2025103(累计签到3天)
BITOP operation destkey key1 [key2...] 多Bitmap位运算(AND/OR/XOR/NOT) BITOP AND sign:all:20251001_02 sign:all:20251001 sign:all:20251002(统计两天都签到的用户)
BITPOS key value [start end] 查询第一个值为0/1的bit位偏移量 BITPOS sign:1001:202510 02(第一个未签到日为10月3日)

完整实操示例:

redis 复制代码
# 设置签到状态
127.0.0.1:6379> SETBIT sign:1001:202510 0 1
(integer) 0
127.0.0.1:6379> SETBIT sign:1001:202510 1 1
(integer) 0
127.0.0.1:6379> SETBIT sign:1001:202510 3 1
(integer) 0

# 查询签到状态
127.0.0.1:6379> GETBIT sign:1001:202510 2
(integer) 0

# 统计签到次数
127.0.0.1:6379> BITCOUNT sign:1001:202510
(integer) 3

# 位运算统计共同签到用户
127.0.0.1:6379> BITOP AND sign:all:20251001_02 sign:all:20251001 sign:all:20251002
(integer) 2
127.0.0.1:6379> BITCOUNT sign:all:20251001_02
(integer) 500

二、HyperLogLog(基数统计)

1. 什么是基数统计?

基数统计指的是统计一个集合中不重复元素的数量,比如"网站今日UV""搜索关键词去重数""用户访问品类数"。

传统的基数统计方案(MySQL distinct count、Redis Set)的问题是:数据量越大,内存占用越高 ,当数据达到亿级时,几乎无法落地。而Redis的HyperLogLog(简称HLL)正是为解决海量数据基数统计而生的。

2. 核心优势

HyperLogLog是一种概率型统计算法,它不存储具体的元素,而是通过统计元素的哈希值特征来估算基数,核心特点:

  • 固定内存占用 :无论统计多少数据,每个HyperLogLog键仅占用12KB内存
  • 支持海量数据:可统计接近2^64个不同元素的基数;
  • 可控的误差率 :标准误差仅为0.81%,在大部分业务场景下完全可接受;
  • 支持合并:多个HLL可合并为一个,用于统计跨维度的基数(如多日UV合并为周UV)。

3. 核心应用场景

HyperLogLog适合不需要获取具体元素,仅需统计不重复数量的场景,典型案例:

  • 网站/APP的UV(独立访客)统计(PV用String INCR即可);
  • 搜索框的关键词去重统计;
  • 电商平台的商品被访问的独立用户数统计;
  • 广告曝光的独立设备数统计。

4. 注意事项

  • HyperLogLog是近似统计,不是精确值,但误差在业务中可接受(如需精确统计,仍用Set/Hash);
  • HyperLogLog不支持删除元素,如果需要实现"按时间窗口统计",建议按天/小时创建独立的HLL键,而非单键追加;
  • 适合超大规模数据 ,如果数据量在10万以内,用Set的SCARD命令更高效(无误差,内存占用差异小)。

5. 核心命令

HyperLogLog的所有命令均以PF开头,核心命令及实操示例如下:

命令 作用 示例
PFADD key element1 [element2...] 向HLL中添加元素(重复元素自动忽略) PFADD uv:20251001 1001 1002 1003 1001 10041(结构更新)
PFCOUNT key [key2...] 统计一个或多个HLL的基数 PFCOUNT uv:202510014(今日UV为4) PFCOUNT uv:20251001 uv:202510026(两日总UV为6)
PFMERGE destkey key1 [key2...] 将多个HLL合并为一个新的HLL PFMERGE uv:202510_week1 uv:20251001 uv:20251002 uv:20251003(合并周UV)

完整实操示例:

redis 复制代码
# 添加UV数据
127.0.0.1:6379> PFADD uv:20251001 1001 1002 1003 1001 1004
(integer) 1

# 统计单日UV
127.0.0.1:6379> PFCOUNT uv:20251001
(integer) 4

# 添加次日UV数据
127.0.0.1:6379> PFADD uv:20251002 1003 1004 1005 1006
(integer) 1

# 统计两日总UV
127.0.0.1:6379> PFCOUNT uv:20251001 uv:20251002
(integer) 6

# 合并多日UV
127.0.0.1:6379> PFMERGE uv:202510_week1 uv:20251001 uv:20251002 uv:20251003
OK
127.0.0.1:6379> PFCOUNT uv:202510_week1
(integer) 8

三、Geospatial(地理空间)

1. 什么是Geospatial?

Redis 3.2版本新增的Geospatial(GEO)类型,是专门用于存储和操作地理空间数据 的扩展,核心支持经纬度存储、距离计算、范围检索 等操作,底层基于Zset实现(将经纬度转换为有序的分数存储)。

Geospatial让Redis可以快速实现轻量级的位置服务,无需依赖专门的地理数据库(如PostGIS),适合中小规模的位置相关业务。

2. 核心应用场景

Geospatial针对带地理位置的业务场景优化,典型案例:

  • 周边商家/门店检索(如"附近5公里的咖啡店");
  • 打车软件的司机/乘客位置匹配;
  • 物流快递的车辆位置追踪;
  • 社交APP的"附近的人"功能。

3. 核心限制

使用Geospatial时需注意经纬度的有效范围,超出范围会报错:

  • 经度:-180° ~ 180°
  • 纬度:-85.05112878° ~ 85.05112878°
  • 不支持直接存储南极、北极的位置。

4. 核心命令

Geospatial的所有命令均以GEO开头,核心命令及实操示例如下:

命令 作用 示例
GEOADD key longitude latitude member [lon2 lat2 member2...] 添加地理位置(经度 纬度 标识) GEOADD china:city 121.47 31.23 shanghai 116.38 39.90 beijing2
GEOPOS key member [member...] 查询指定标识的经纬度 GEOPOS china:city shanghai beijing(返回上海、北京经纬度)
GEODIST key member1 member2 [unit] 计算两个位置的距离(单位:m/km/ft/mi) GEODIST china:city beijing shanghai km"1068.1535"
GEORADIUS key longitude latitude radius unit [OPTIONS] 根据经纬度检索指定范围内的位置 GEORADIUS china:city 110 30 1000 km WITHDIST(检索指定坐标周边城市)
GEORADIUSBYMEMBER key member radius unit [OPTIONS] 根据已有标识检索其周围指定范围的位置 GEORADIUSBYMEMBER china:city shanghai 800 km WITHPOS WITHDIST(检索上海周边城市)
GEOHASH key member [member...] 返回位置的Geohash编码 GEOHASH china:city shanghai beijing["wtw3sjzb4s0", "wx4g0s8q3e0"]

完整实操示例:

redis 复制代码
# 添加城市经纬度
127.0.0.1:6379> GEOADD china:city 121.47 31.23 shanghai 116.38 39.90 beijing 106.50 29.53 chongqing 114.05 22.52 shenzhen
(integer) 4

# 查询城市经纬度
127.0.0.1:6379> GEOPOS china:city shanghai beijing
1) 1) "121.47000163793563843"
   2) "31.22999903975783553"
2) 1) "116.38000041246414185"
   2) "39.90000009167092543"

# 计算城市间距离
127.0.0.1:6379> GEODIST china:city beijing shanghai km
"1068.1535"

# 按坐标检索周边城市
127.0.0.1:6379> GEORADIUS china:city 110 30 1000 km WITHDIST
1) 1) "chongqing"
   2) "341.9370"
2) 1) "shenzhen"
   2) "924.6479"

# 按城市检索周边城市
127.0.0.1:6379> GEORADIUSBYMEMBER china:city shanghai 800 km WITHPOS WITHDIST
1) 1) "shanghai"
   2) "0.0000"
   3) 1) "121.47000163793563843"
      2) "31.22999903975783553"

# 获取Geohash编码
127.0.0.1:6379> GEOHASH china:city shanghai beijing
1) "wtw3sjzb4s0"
2) "wx4g0s8q3e0"

如果我的内容对你有帮助,请 点赞 , 评论 , 收藏 。创作不易,大家的支持就是我坚持下去的动力!

相关推荐
dc_00121 小时前
MySQL无法连接到本地localhost的解决办法2024.11.8
数据库·mysql·adb
SQL必知必会2 小时前
使用 SQL 实现帕累托原则(80/20 法则)
大数据·数据库·sql
2401_848009723 小时前
Redis零基础入门学习
数据库·redis·学习
NEXT063 小时前
2026 技术风向:为什么在 AI 时代,PostgreSQL 彻底成为了全栈工程师的首选数据库
前端·数据库·ai编程
Tangcan-3 小时前
在Ubuntu 22.04上安装redis
linux·redis·ubuntu
hzc09876543213 小时前
MySQL大小写敏感、MySQL设置字段大小写敏感
数据库·mysql
w***29853 小时前
MySql中的事务、MySql事务详解、MySql隔离级别
数据库·mysql·adb
zhanglinping6193 小时前
MySQL——内置函数
android·数据库·mysql
m***78743 小时前
mysql之字符串函数
android·数据库·mysql