【Redis】4、详解三种特殊数据类型 Geospatial、Hyperloglog、Bitmap

本文主要是介绍【Redis】4、详解三种特殊数据类型 Geospatial、Hyperloglog、Bitmap,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

这三种特殊数据类型其实不是一个新的类型;底层还是五大类型中的一种;如:Zset、String

1、Geospatial 地理位置

geo:地理位置 spatial: [ˈspeɪʃl] 空间的

朋友的定位,附近的人,打车距离计算?

Redis 的 Geo 在Redis3.2 版本就推出了! 这个功能可以推算地理位置的信息,两地之间的距离,方圆
几里的人!

可以查询一些测试数据:http://www.jsons.cn/lngcodeinfo/0706D99C19A781A3/

在这里插入图片描述

官方文档:Redis命令中心 GEO

1)添加地理位置

  • geoadd key [NX|XX] [CH] longitude latitude member [longitude latitude member ...] 添加一个或多个位置的经度、纬度;先经度,后纬度

规则

  • 有效的经度从 -180 度到 180
  • 有效的纬度从 -85.05112878 度到 85.05112878

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

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

# 添加北京经纬度
127.0.0.1:6379> geoadd china:city 116.405285 39.904989 beijing
(integer) 1# 查看key
127.0.0.1:6379> keys *
1) "china:city"# key类型:zset
127.0.0.1:6379> type china:city
zset# 添加上海、广州、重庆
127.0.0.1:6379> geoadd china:city 121.47264 31.231706 shanghai 113.28063 23.125178 guangzhou 106.504962 29.533155 chongqing
(integer) 3# 查询全部
127.0.0.1:6379> zrange china:city 0 -1
1) "chongqing"
2) "guangzhou"
3) "shanghai"
4) "beijing"

2)获取经纬度

  • geopos key member [member ...] 获取一个或多个位置的经纬度
127.0.0.1:6379> geopos china:city chongqing guangzhou
1) 1) "106.50495976209640503"2) "29.53315530684997015"
2) 1) "113.28062742948532104"2) "23.12517743834835215"

3)获取两地间的距离

  • geodist key member1 member2 [m|km|ft|mi] 获取两个位置成员间的距离

单位

  • m 表示单位为米(默认)
  • km 表示单位为千米
  • mi 表示单位为英里
  • ft 表示单位为英尺
# 北京、上海间的距离
127.0.0.1:6379> geodist china:city beijing shanghai km
"1067.5978"
# 广州、重庆间的距义
127.0.0.1:6379> geodist china:city guangzhou chongqing
"981476.5000"

4)找出特定坐标范围内的其它元素

  • georadius key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] 获取特定位置为中心,radius为半径的范围的其它位置
    • longitude latitude 中心坐标
    • radius m|km|ft|mi 半径及单位;中间有空格
    • withcoord 将位置元素的经度和纬度也一并返回
    • withdist 与中心之间的距离也一并返回
    • withhash 位置哈希值一并返回
    • count 返回元素的数量

我附近的人? (获得所有附近的人的地址,定位!)通过半径来查询!

获得指定数量的人,200

所有数据应该都录入:china:city ,才会让结果更加请求!

# 找出距离位置(100,30)方圆500km的其它城市
127.0.0.1:6379> georadius china:city 100 30 500 km
(empty array)# 找出距离位置(100,30)方圆1000km的其它城市,包含经纬度、距离、哈希值
127.0.0.1:6379> georadius china:city 100 30 1000 km withcoord withdist withhash
1) 1) "chongqing"2) "630.1140"3) (integer) 40260421178873714) 1) "106.50495976209640503"2) "29.53315530684997015"

5)找出特定成员范围内的其它元素

  • georadiusbymember key member radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] 找出距离member成员,方圆radius范围内的其它成员
127.0.0.1:6379> georadiusbymember china:city beijing 100 km
1) "beijing"
127.0.0.1:6379> georadiusbymember china:city beijing 1000 km
1) "beijing"
127.0.0.1:6379> georadiusbymember china:city beijing 2000 km
1) "chongqing"
2) "guangzhou"
3) "shanghai"
4) "beijing"127.0.0.1:6379> georadiusbymember china:city beijing 2000 km withcoord withdist withhash
1) 1) "chongqing"2) "1464.2210"3) (integer) 40260421178873714) 1) "106.50495976209640503"2) "29.53315530684997015"
2) 1) "guangzhou"2) "1889.3707"3) (integer) 40465337640664754) 1) "113.28062742948532104"2) "23.12517743834835215"
3) 1) "shanghai"2) "1067.5978"3) (integer) 40548034648170624) 1) "121.47264093160629272"2) "31.23170490709807012"
4) 1) "beijing"2) "0.0000"3) (integer) 40698853706710104) 1) "116.40528291463851929"2) "39.9049884229125027"

6)返回位置的哈希字符串

  • geohash key member [member ...] 返回一个或多个位置元素的哈希字符串(11个字符)
# 将二维的经纬度转换为一维的字符串,如果两个字符串越接近,那么则距离越近!
127.0.0.1:6379> geohash china:city beijing chongqing
1) "wx4g0b7xrt0"
2) "wm78p86e170"

7)底层原理

GEO 底层的实现原理其实就是 Zset!可以使用Zset命令来操作geo!

127.0.0.1:6379> keys *
1) "china:city"
# key类型zset
127.0.0.1:6379> type china:city
zset# 查看所有
127.0.0.1:6379> zrange china:city 0 -1
1) "chongqing"
2) "guangzhou"
3) "shanghai"
4) "beijing"# 删除
127.0.0.1:6379> zrem china:city chongqing
(integer) 1
127.0.0.1:6379> zrange china:city 0 -1
1) "guangzhou"
2) "shanghai"
3) "beijing"

2、Hyperloglog

1)介绍

走近源码:神奇的HyperLogLog - 知乎 (zhihu.com)

2)应用场景

  • 统计注册 IP 数
  • 统计每日访问 IP 数
  • 统计页面实时 UV 数
  • 统计在线用户数
  • 统计用户每天搜索不同词条的个数

网页的访问量 UV (一个人访问一个网站多次,但是还是算作一个人!)

传统的方式,set 保存用户的id,然后就可以统计 set 中的元素数量作为标准判断!这个方式如果保存大量的用户id,就会比较麻烦!我们的目的是为了计数,而不是保存用户id;

使用HyperLogLog非常合适;

HyperLogLog有0.81% 错误率! 统计UV任务,可以忽略不计的!

如果允许容错,那么一定可以使用 Hyperloglog !

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

3)添加 pfadd

  • pfadd key element [element ...] 向key中添加一个或多个元素
# 向mykey1中添加v1、v2、v3
127.0.0.1:6379> pfadd mykey1 v1 v2 v3
(integer) 1# key:mykey1
127.0.0.1:6379> keys *
1) "mykey1"# key的类型 string
127.0.0.1:6379> type mykey1
string# 元素数量 (数据量大时有误差)
127.0.0.1:6379> pfcount mykey1
(integer) 3# 字符串的值(无法查看mykey1中的具体元素)
127.0.0.1:6379> getrange mykey1 0 -1
"HYLL\x01\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00G\x1f\x80o4\x88@P\x8cIV"

4)数量 pfcount

  • pfcount key [key ...] 获取一个或多个key中不重复元素的总数量
# 向mykey2中添加v10 v11 v12
127.0.0.1:6379> pfadd mykey2 v10 v11 v12
(integer) 1# mykey1中元素数量
127.0.0.1:6379> pfcount mykey1
(integer) 3 # 分别为v1 v2 v3
# 再向mykey1中添加v11
127.0.0.1:6379> pfadd mykey1 v11
(integer) 1
# mykey1中元素数量
127.0.0.1:6379> pfcount mykey1
(integer) 4 # 分别为v1 v2 v3 v11# mykey1和mykey2中元素的总数量(不重复元素)
127.0.0.1:6379> pfcount mykey1 mykey2
(integer) 6

5)合并 pfmerge

  • pfmerge destkey sourcekey [sourcekey ...] 把一个或多个sourcekey合并到一个目标destkey中
127.0.0.1:6379> keys *
1) "mykey2"
2) "mykey1"# 把mykey1、mykey2合并到mykey3
127.0.0.1:6379> pfmerge mykey3 mykey1 mykey2
OK127.0.0.1:6379> keys *
1) "mykey3"
2) "mykey2"
3) "mykey1"# mykey3中不重复元素的个数;效果等同于pfcount mykey1 mykey2
127.0.0.1:6379> pfcount mykey3
(integer) 6

3、Bitmap

原文链接:Redis 中 BitMap 的使用场景

1)概念

BitMap 原本的含义是用一个比特位来映射某个元素的状态。由于一个比特位只能表示 01 两种状态,所以 BitMap 能映射的状态有限,但是使用比特位的优势是能大量的节省内存空间

在 Redis 中,可以把 Bitmap 想象成一个以比特位为单位的数组,数组的每个单元只能存储0和1,数组的下标在 Bitmap 中叫做偏移量

在这里插入图片描述

需要注意的是:BitMap 在 Redis 中并不是一个新的数据类型,其底层是 Redis 的 String 类型。

2)相关命令

(1)设置值 setbit

# 设置值,其中value只能是 0 和 1
setbit key offset value

(2)获取值 getbit

# 获取值
getbit key offset

(3)获取1的个数 bitcount

# 获取指定范围内值为 1 的个数
# start 和 end 以字节为单位
bitcount key start end

(4)BitMap间运算 bitop

# BitMap间的运算
# operations 位移操作符,枚举值AND 与运算 &OR 或运算 |XOR 异或 ^NOT 取反 ~
# result 计算的结果,会存储在该key中
# key1 … keyn 参与运算的key,可以有多个,空格分割,not运算只能一个key
# 当 BITOP 处理不同长度的字符串时,较短的那个字符串所缺少的部分会被看作 0。返回值是保存到 destkey 的字符串的长度(以字节byte为单位),和输入 key 中最长的字符串长度相等。
bitop [operations] [result] [key1] [keyn…]

(5)值第一次出现的位置 bitpos

# 返回指定key中第一次出现指定value(0/1)的位置
bitpos [key] [value]

3)占用空间

在弄清 BitMap 到底占用多大的空间之前,我们再来重申下:Redis 其实只支持 5 种数据类型,并没有 BitMap 这种类型,BitMap 底层是基于 Redis 的字符串类型实现的。

我们通过下面的命令来看下 BitMap 占用的空间大小:

# 首先将偏移量是0的位置设为1;其中 csx:key:1 表示一个key
127.0.0.1:6379> setbit csx:key:1 0 1
(integer) 0
# 通过STRLEN命令,我们可以看到字符串的长度是1
127.0.0.1:6379> STRLEN csx:key:1
(integer) 1
# 将偏移量是1的位置设置为1
127.0.0.1:6379> setbit csx:key:1 1 1
(integer) 0
# 此时字符串的长度还是为1,因为一个字符串有8个比特位,不需要再开辟新的内存空间
127.0.0.1:6379> STRLEN csx:key:1
(integer) 1
# 将偏移量是8的位置设置成1
127.0.0.1:6379> setbit csx:key:1 8 1
(integer) 0
# 此时字符串的长度编程2,因为一个字节存不下9个比特位,需要再开辟一个字节的空间
127.0.0.1:6379> STRLEN csx:key:1
(integer) 2

通过上面的实验我们可以看出,BitMap 占用的空间,就是底层字符串占用的空间。假如 BitMap 偏移量的最大值是 OFFSET_MAX,那么它底层占用的空间就是:

(OFFSET_MAX/8)+1 = 占用字节数

因为字符串内存只能以字节分配,所以上面的单位是字节。

但是需要注意,Redis 中字符串的最大长度是 512M,所以 BitMap 的 offset 值也是有上限的,其最大值是:

8 * 1024 * 1024 * 512  =  2^32

由于 C语言中字符串的末尾都要存储一位分隔符,所以实际上 BitMap 的 offset 值上限是:

(8 * 1024 * 1024 * 512) -1  =  2^32 - 1

4)使用场景

1. 用户签到

很多网站都提供了签到功能,并且需要展示最近一个月的签到情况,这种情况可以使用 BitMap 来实现。
根据日期 offset = (今天是一年中的第几天) % (今年的天数),key = 年份:用户id

如果需要将用户的详细签到信息入库的话,可以考虑使用一个一步线程来完成。

2. 统计活跃用户(用户登陆情况)

使用日期作为 key,然后用户 id 为 offset,如果当日活跃过就设置为1。具体怎么样才算活跃这个标准大家可以自己指定。

假如 20201009 活跃用户情况是: [1,0,1,1,0]
20201010 活跃用户情况是 :[ 1,1,0,1,0 ]

统计连续两天活跃的用户总数:

# 合并两天的key
bitop and dest1 20201009 20201010 
# dest1 中值为1的offset,就是连续两天活跃用户的ID
bitcount dest1

统计20201009 ~ 20201010 活跃过的用户:

# 或运算(并集)
bitop or dest2 20201009 20201010 

3. 统计用户是否在线

如果需要提供一个查询当前用户是否在线的接口,也可以考虑使用 BitMap 。即节约空间效率又高,只需要一个 key,然后用户 id 为 offset,如果在线就设置为 1,不在线就设置为 0。

4. 实现布隆过滤器

这篇关于【Redis】4、详解三种特殊数据类型 Geospatial、Hyperloglog、Bitmap的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/345056

相关文章

CSS place-items: center解析与用法详解

《CSSplace-items:center解析与用法详解》place-items:center;是一个强大的CSS简写属性,用于同时控制网格(Grid)和弹性盒(Flexbox)... place-items: center; 是一个强大的 css 简写属性,用于同时控制 网格(Grid) 和 弹性盒(F

spring中的ImportSelector接口示例详解

《spring中的ImportSelector接口示例详解》Spring的ImportSelector接口用于动态选择配置类,实现条件化和模块化配置,关键方法selectImports根据注解信息返回... 目录一、核心作用二、关键方法三、扩展功能四、使用示例五、工作原理六、应用场景七、自定义实现Impor

一文深入详解Python的secrets模块

《一文深入详解Python的secrets模块》在构建涉及用户身份认证、权限管理、加密通信等系统时,开发者最不能忽视的一个问题就是“安全性”,Python在3.6版本中引入了专门面向安全用途的secr... 目录引言一、背景与动机:为什么需要 secrets 模块?二、secrets 模块的核心功能1. 基

一文详解MySQL如何设置自动备份任务

《一文详解MySQL如何设置自动备份任务》设置自动备份任务可以确保你的数据库定期备份,防止数据丢失,下面我们就来详细介绍一下如何使用Bash脚本和Cron任务在Linux系统上设置MySQL数据库的自... 目录1. 编写备份脚本1.1 创建并编辑备份脚本1.2 给予脚本执行权限2. 设置 Cron 任务2

一文详解如何在idea中快速搭建一个Spring Boot项目

《一文详解如何在idea中快速搭建一个SpringBoot项目》IntelliJIDEA作为Java开发者的‌首选IDE‌,深度集成SpringBoot支持,可一键生成项目骨架、智能配置依赖,这篇文... 目录前言1、创建项目名称2、勾选需要的依赖3、在setting中检查maven4、编写数据源5、开启热

Python常用命令提示符使用方法详解

《Python常用命令提示符使用方法详解》在学习python的过程中,我们需要用到命令提示符(CMD)进行环境的配置,:本文主要介绍Python常用命令提示符使用方法的相关资料,文中通过代码介绍的... 目录一、python环境基础命令【Windows】1、检查Python是否安装2、 查看Python的安

HTML5 搜索框Search Box详解

《HTML5搜索框SearchBox详解》HTML5的搜索框是一个强大的工具,能够有效提升用户体验,通过结合自动补全功能和适当的样式,可以创建出既美观又实用的搜索界面,这篇文章给大家介绍HTML5... html5 搜索框(Search Box)详解搜索框是一个用于输入查询内容的控件,通常用于网站或应用程

Redis Cluster模式配置

《RedisCluster模式配置》:本文主要介绍RedisCluster模式配置,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录分片 一、分片的本质与核心价值二、分片实现方案对比 ‌三、分片算法详解1. ‌范围分片(顺序分片)‌2. ‌哈希分片3. ‌虚

Python中使用uv创建环境及原理举例详解

《Python中使用uv创建环境及原理举例详解》uv是Astral团队开发的高性能Python工具,整合包管理、虚拟环境、Python版本控制等功能,:本文主要介绍Python中使用uv创建环境及... 目录一、uv工具简介核心特点:二、安装uv1. 通过pip安装2. 通过脚本安装验证安装:配置镜像源(可

C++ 函数 strftime 和时间格式示例详解

《C++函数strftime和时间格式示例详解》strftime是C/C++标准库中用于格式化日期和时间的函数,定义在ctime头文件中,它将tm结构体中的时间信息转换为指定格式的字符串,是处理... 目录C++ 函数 strftipythonme 详解一、函数原型二、功能描述三、格式字符串说明四、返回值五