【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

相关文章

MySQL数据库双机热备的配置方法详解

《MySQL数据库双机热备的配置方法详解》在企业级应用中,数据库的高可用性和数据的安全性是至关重要的,MySQL作为最流行的开源关系型数据库管理系统之一,提供了多种方式来实现高可用性,其中双机热备(M... 目录1. 环境准备1.1 安装mysql1.2 配置MySQL1.2.1 主服务器配置1.2.2 从

Linux kill正在执行的后台任务 kill进程组使用详解

《Linuxkill正在执行的后台任务kill进程组使用详解》文章介绍了两个脚本的功能和区别,以及执行这些脚本时遇到的进程管理问题,通过查看进程树、使用`kill`命令和`lsof`命令,分析了子... 目录零. 用到的命令一. 待执行的脚本二. 执行含子进程的脚本,并kill2.1 进程查看2.2 遇到的

MyBatis常用XML语法详解

《MyBatis常用XML语法详解》文章介绍了MyBatis常用XML语法,包括结果映射、查询语句、插入语句、更新语句、删除语句、动态SQL标签以及ehcache.xml文件的使用,感兴趣的朋友跟随小... 目录1、定义结果映射2、查询语句3、插入语句4、更新语句5、删除语句6、动态 SQL 标签7、ehc

详解SpringBoot+Ehcache使用示例

《详解SpringBoot+Ehcache使用示例》本文介绍了SpringBoot中配置Ehcache、自定义get/set方式,并实际使用缓存的过程,文中通过示例代码介绍的非常详细,对大家的学习或者... 目录摘要概念内存与磁盘持久化存储:配置灵活性:编码示例引入依赖:配置ehcache.XML文件:配置

从基础到高级详解Go语言中错误处理的实践指南

《从基础到高级详解Go语言中错误处理的实践指南》Go语言采用了一种独特而明确的错误处理哲学,与其他主流编程语言形成鲜明对比,本文将为大家详细介绍Go语言中错误处理详细方法,希望对大家有所帮助... 目录1 Go 错误处理哲学与核心机制1.1 错误接口设计1.2 错误与异常的区别2 错误创建与检查2.1 基础

k8s按需创建PV和使用PVC详解

《k8s按需创建PV和使用PVC详解》Kubernetes中,PV和PVC用于管理持久存储,StorageClass实现动态PV分配,PVC声明存储需求并绑定PV,通过kubectl验证状态,注意回收... 目录1.按需创建 PV(使用 StorageClass)创建 StorageClass2.创建 PV

Python版本信息获取方法详解与实战

《Python版本信息获取方法详解与实战》在Python开发中,获取Python版本号是调试、兼容性检查和版本控制的重要基础操作,本文详细介绍了如何使用sys和platform模块获取Python的主... 目录1. python版本号获取基础2. 使用sys模块获取版本信息2.1 sys模块概述2.1.1

一文详解Python如何开发游戏

《一文详解Python如何开发游戏》Python是一种非常流行的编程语言,也可以用来开发游戏模组,:本文主要介绍Python如何开发游戏的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下... 目录一、python简介二、Python 开发 2D 游戏的优劣势优势缺点三、Python 开发 3D

Redis 基本数据类型和使用详解

《Redis基本数据类型和使用详解》String是Redis最基本的数据类型,一个键对应一个值,它的功能十分强大,可以存储字符串、整数、浮点数等多种数据格式,本文给大家介绍Redis基本数据类型和... 目录一、Redis 入门介绍二、Redis 的五大基本数据类型2.1 String 类型2.2 Hash

Java中的.close()举例详解

《Java中的.close()举例详解》.close()方法只适用于通过window.open()打开的弹出窗口,对于浏览器的主窗口,如果没有得到用户允许是不能关闭的,:本文主要介绍Java中的.... 目录当你遇到以下三种情况时,一定要记得使用 .close():用法作用举例如何判断代码中的 input