Redis:新的3种数据类型Bitmaps、HyperLoglog、Geographic

目录

  • Bitmaps
    • 简介
    • 常用命令
    • bitmaps与set比较
  • HyperLoglog
    • 简介
    • 命令
  • Geographic
    • 简介
    • 命令

Bitmaps

简介

位操作字符串。

现代计算机使用二进制(位)作为信息的基本单位,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中叫做偏移量。

在这里插入图片描述

常用命令

  1. setbit

设置某个偏移量的值(0或1)。

SETBIT key offset value

设置offset偏移位的值为value,offset的值是从0开始的,n代表第n+1个bit位置的。
offset 参数必须大于或等于 0 ,小于 2^32 (bit 映射被限制在 512 MB 之内)。
value 的值只能为0或1

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

示例:

redis> SETBIT bit 10086 1 
(integer) 0 
redis> GETBIT bit 10086 
(integer) 1 
redis> GETBIT bit 100 # bit 默认被初始化为 0 
(integer) 0

例如每个独立用户是否访问过网站存放在bitmaps中,将访问的用户记做1,没有访问的用户记做0,用户id作为offset。

假设现在有20个用户,userid=1,6,11,15,19的用户对网站进行了访问,那么当前bitmaps初始化结果如图
在这里插入图片描述

users:20220409 这个bitmaps中表示2022-04-09这天独立访问的用户,如下

127.0.0.1:6379> setbit users:20220409 1 1 
(integer) 0 
127.0.0.1:6379> setbit users:20220409 6 1 
(integer) 0 
127.0.0.1:6379> setbit users:20220409 11 1 
(integer) 0 
127.0.0.1:6379> setbit users:20220409 15 1 
(integer) 0 
127.0.0.1:6379> setbit users:20220409 19 1 
(integer) 0
  1. getbit

获取某个偏移位的值.

GETBIT key offset

获取key所对应的bitmaps中offset偏移位的值。

返回值:0或者1

示例

127.0.0.1:6379> setbit users 1001 1 #设置偏移量1001的bit位的值为1 
(integer) 0 
127.0.0.1:6379> getbit users 1001 #获取偏移位1001的bit位的值 
(integer) 1 
127.0.0.1:6379> getbit users 1000 #获取偏移位1000的bit位的值,未设置,返回0 
(integer) 0
  1. bitcount

统计bit位都为1的数量

BITCOUNT key [start] [end]

统计字符串被设置为1的bit数,一般情况下,给定的整个字符串都会被进行统计,通过指定额外的

start或者end参数,可以让计数只在特定的位上进行, start 和 end 参数,都可以使用负数值:

比如 -1 表示最后一个位,而 -2 表示倒数第二个位,以此类推。

注意了:start、end是指bit组的字节的下标数,一个直接对应8个bit,所以[a,b]对应的offset范围是[8a,8b+7]

示例:

127.0.0.1:6379> setbit user 7 1 # 设置user这个bitmaps中偏移量为7的bit为值为1,也就是第8 个bit位的值 
(integer) 0 
127.0.0.1:6379> setbit user 15 1 # 设置user这个bitmaps中偏移量为15的bit为值为1 
(integer) 0 
127.0.0.1:6379> setbit user 23 1 # 设置user这个bitmaps中偏移量为23的bit为值为1 
(integer) 0 
127.0.0.1:6379> bitcount user # 获取user这个bitmaps中1的数量 
(integer) 3 
127.0.0.1:6379> bitcount user 0 1 # 获取[0,1]这个字节内bit位上1的数量,也就是offset是 [0,15]的位置上1的数量,所以是2个 
(integer) 2 
127.0.0.1:6379> bitcount user 0 0 # 获取[0,0]这个字节内bit位上1的数量,也就是offset是 [0,7]的位置上1的数量,只有7这个位置,所以是1个 
(integer) 1
  1. bittop

对一个多个bitmaps执行位操作。

BITOP operation destkey key [key ...]

对一个或多个保存二进制位的字符串 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 中最长的字符串长度相等。

示例

redis> SETBIT bits-1 0 1 # bits-1 = 1001 
(integer) 0 
redis> SETBIT bits-1 3 1 
(integer) 0 
redis> SETBIT bits-2 0 1 # bits-2 = 1011 
(integer) 0 
redis> SETBIT bits-2 1 1 
(integer) 0 
redis> SETBIT bits-2 3 1 
(integer) 0 
redis> BITOP AND and-result bits-1 bits-2 
(integer) 1
redis> GETBIT and-result 0      # and-result = 1001
(integer) 1
redis> GETBIT and-result 1 
(integer) 0 
redis> GETBIT and-result 2 
(integer) 0 
redis> GETBIT and-result 3 
(integer) 1

bitmaps与set比较

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

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

在这里插入图片描述

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

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

在这里插入图片描述

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

在这里插入图片描述

HyperLoglog

简介

在工作当中,我们经常会遇到与统计相关的功能需求,比如统计网站 PV(PageView 页面访问量),可以使用 Redis 的 incr、incrby 轻松实现。但像 UV(UniqueVisitor 独立访客)、独立 IP 数、搜索记录数等需要去重和计数的问题如何解决?这种求集合中不重复元素个数的问题称为基数问题。

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

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

使用 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。 基数估计就是在误差可接受的范围内,快速计算基数。

命令

  1. pfadd

添加多个元素。

pfadd key element [element ...]

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

**返回值:**1:添加成功;0:添加失败

示例

127.0.0.1:6379> pfadd program java php c c++ # program中添加4个元素 [java,php,c,c++],添加成功发,返回1 
(integer) 1 
127.0.0.1:6379> pfadd program java # 再次添加java,由于已经存在,所以添加失败,返回0 
(integer) 0 
127.0.0.1:6379> pfadd program java js # 再次添加2个元素,java已经存在了,但是js不存在, 添加成功,返回1 
(integer) 1
  1. pfcount

获取多个HLL合并后元素的个数。

pfcount key1 key2 ...

统计一个或者多个key去重后元素的数量。

示例

127.0.0.1:6379> pfadd uv1 a b c d e #uv1中5个元素:[a,b,c,d,e] 
(integer) 1 
127.0.0.1:6379> pfcount uv1 #uv1中数量为5 
(integer) 5 
127.0.0.1:6379> pfadd uv2 b c d e f #uv2中5个元素:[b,c,d,e,f] 
(integer) 1 
127.0.0.1:6379> pfcount uv2 #uv2中数量为5
(integer) 5 
127.0.0.1:6379> pfcount uv1 uv2 # 获取uv1和uv2去重之后数量合集:[a,b,c,d,e,f],数量为5 
(integer) 5
  1. pfmerge

将多个HLL合并后元素放入另外一个HLL

pfmerge destkey sourcekey [sourcekey ...]

将多个 sourcekey 合并后放到 destkey 中。

示例

127.0.0.1:6379> pfadd uv1 a b c d e #uv1中5个元素:[a,b,c,d,e] 
(integer) 1 
127.0.0.1:6379> pfcount uv1 #uv1中数量为5 
(integer) 5 
127.0.0.1:6379> pfadd uv2 b c d e f #uv2中5个元素:[b,c,d,e,f] 
(integer) 1 
127.0.0.1:6379> pfcount uv2 #uv2中数量为5 
(integer) 5 
127.0.0.1:6379> pfmerge uv_dest uv1 uv2 #将uv1和uv2合并后放入uv_dest 
OK
127.0.0.1:6379> pfcount uv_dest #uv_dest元素个数为6 
(integer) 6

Geographic

简介

Reids3.2 中增加了对GEO类型的支持,GEO(Geographic),地理信息的缩写。该类型,就是元素的 2 维坐标,在地图上就是经纬度,redis基于该类型,提供了经纬度设置、查询、范围查询、距离查询,经纬度Hash等常见操作。

命令

  1. geoadd

添加多个位置的经纬度。

geoadd key longitude latitude member [longitude latitude member ...]

longitude latitude member:经度 纬度 名称

示例

127.0.0.1:6379> geoadd china:city 121.47 31.23 shanghai #添加上海的经纬度 
(integer) 1 
127.0.0.1:6379> geoadd china:city 106.50 29.53 chongqing 114.05 22.52 shenzhen 116.38 39.90 beijing #添加重庆、深圳、北京 3 个城市的经纬度 
(integer) 3 
127.0.0.1:6379> type china:city #发现geo实际上使用zset类型存储的 
zset 
127.0.0.1:6379> zrange china:city 0 -1 
1) "chongqing" 2) "shenzhen" 3) "shanghai" 4) "beijing" 
127.0.0.1:6379> zrange china:city 0 -1 withscores 
1) "chongqing" 2) "4026042091628984" 3) "shenzhen" 4) "4046432193584628" 5) "shanghai" 6) "4054803462927619" 7) "beijing" 8) "4069885332386336"

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

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

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

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

  1. geopos

获取多个位置的坐标值

geopos key member [member ...]

示例

127.0.0.1:6379> geoadd china:city 121.47 31.23 shanghai #添加上海的经纬度 
(integer) 1 
127.0.0.1:6379> geoadd china:city 106.50 29.53 chongqing 114.05 22.52 shenzhen 116.38 39.90 beijing #添加重庆、深圳、北京 3 个城市的经纬度 
(integer) 3 
127.0.0.1:6379> geopos china:city wuhan beijing chongqing #获取武汉、北京、重庆 3个城 市的坐标,由于没有添加武汉的数据,所以没有获取到,其他2个获取到了 
1) (nil) 
2) 1) "116.38000041246414185" 2) "39.90000009167092543"
3) 1) "106.49999767541885376" 2) "29.52999957900659211"
  1. geodist

获取两个位置的直线距离

geodist key member1 member2 [m|km|ft|mi]

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

示例

127.0.0.1:6379> geoadd china:city 
121.47 31.23 shanghai #添加上海的经纬度 
(integer) 1 
127.0.0.1:6379> geoadd china:city 106.50 29.53 chongqing 114.05 22.52 shenzhen 116.38 39.90 beijing #添加重庆、深圳、北京 3 个城市的经纬度 
(integer) 3
127.0.0.1:6379> geodist china:city beijing chongqing km #获取北京到重庆的直线距离 
"1462.9505"
  1. georadius

以给定的经纬度为中心,找出某一半径内的元素

georadius key longitude latitude radius m|km|ft|mi

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

示例

127.0.0.1:6379> geoadd china:city 121.47 31.23 shanghai #添加上海的经纬度 
(integer) 1 
127.0.0.1:6379> geoadd china:city 106.50 29.53 chongqing 114.05 22.52 shenzhen 116.38 39.90 beijing #添加重庆、深圳、北京 3 个城市的经纬度
(integer) 3 
127.0.0.1:6379> georadius china:city 110 30 1000 km #在china:city中检索:以经纬度 (110,30)为中心,半径为1000km内的位置列表 
1) "chongqing" 
2) "shenzhen"

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/156188.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Parallel Diffusion Models of Operator and Image for Blind Inverse Problems

盲逆问题算子和图像的并行扩散模型 论文链接:https://arxiv.org/abs/2211.10656 项目链接:https://github.com/BlindDPS/blind-dps Abstract 在正向算子已知的情况下(即非盲),基于扩散模型的逆问题求解器已经展示了最先进的性能。然而&…

css鼠标横向滚动并且不展示滚动条几种方法

需求&#xff1a;实现内容超出之后使用属性滚轮进行左右查看超出内容&#xff0c;并且隐藏滚动条 1.不使用框架实现 每次滚动就滚动40px的距离 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name&quo…

STM32——STM32Cubemx的学习使用总结

文章目录 一、简介二、STM32Cube IDE与MX区别&#xff1f;三、界面介绍和使用四、使用整体框架 一、简介 STM32CubeMX是一个图形化工具&#xff0c;可以非常容易地配置STM32微控制器和微处理器&#xff0c;以及为ArmCortex-M 内核或部分 Linux 设备树生成相应的初始化C代码&…

编译器优化代码研究

《Effective C》条款21&#xff1a; /** * 结论&#xff1a;对自定义类型对象表达式objA*objB objC; * 定义friend MyInt operator*(const MyInt& lhs,const MyInt& rhs) * 编译器优化后&#xff1a;operator*()函数内直接在调用接收处构造(此处的匿名临时对象)&am…

CANopen权威指南【CAN总线协议】

1这个总线定义是老外发明的。 想要使用&#xff0c;就必须按照协议去配置数据帧。 CIA301和cia402协议&#xff0c;实际就是寄存器地址上某一段的定义。 下载地址&#xff1a; CAN in Automation (CiA): Technical documents 注册下载也是非常快的。【没什么难度】 就是资…

HTTP响应详解

HTTP响应格式 HTTP响应报文通常由四个部分组成: 响应行(Response Line):包含协议版本、状态码和状态消息,例如:HTTP/1.1 200 OK。 响应头(Response Headers):包含了一系列的键值对,用来描述关于响应的信息,比如内容类型、日期、服务器信息等等。 空行:即CRLF(回车…

关于使用Java-JWT的笔记

Token的组成规则 一个token分三部分&#xff0c;按顺序为&#xff1a;头部&#xff08;header)&#xff0c;载荷&#xff08;payload)&#xff0c;签证&#xff08;signature) 由三部分生成token &#xff0c;三部分之间用“.”号做分隔。 例如&#xff1a;“eyJhbGciOiJIUzI1…

完全二叉树你需要了解一下

完全二叉树介绍完全二叉树应用场景完全二叉树和满二叉树的区别完全二叉树代码示例拓展 完全二叉树介绍 完全二叉树&#xff08;Complete Binary Tree&#xff09;是一种特殊的二叉树&#xff0c;它的定义是&#xff1a;如果设二叉树的深度为h&#xff0c;除第h层外&#xff0c…

博主都在用的网站,一键制作电子杂志

​随着互联网的发展&#xff0c;越来越多的人开始使用电子杂志来展示自己的作品或宣传自己的品牌。而制作电子杂志的工具也越来越多&#xff0c;其中一些工具非常受欢迎&#xff0c;被许多博主使用。今天&#xff0c;我们就来介绍一款博主都在用的网站&#xff0c;它可以帮助你…

MySQL InnoDB 引擎底层解析(三)

6.3.3. InnoDB 的内存结构总结 InnoDB 的内存结构和磁盘存储结构图总结如下&#xff1a; 其中的 Insert/Change Buffer 主要是用于对二级索引的写入优化&#xff0c;Undo 空间则是 undo 日志一般放在系统表空间&#xff0c;但是通过参数配置后&#xff0c;也可以用独立表空 间…

c语言上机作业:迭代法求平方根

1.题目 设计一个函数func用迭代法编程求一个数的平方根。平方根的迭代公式为&#xff1a;牛顿迭代法&#xff0c;(要求前后两次迭代值求差的绝对值小于10的-9次方) 2.思路 a.这里要求我们设置一个函数能够完成牛顿迭代法&#xff0c;这里需要使用到函数迭代的知识&#xff0…

泉盛UV-K5/K6全功能中文固件

https://github.com/wu58430/uv-k5-firmware-chinese/releases 主要功能&#xff1a; 中文菜单 许多来自 OneOfEleven 的模块&#xff1a; AM 修复&#xff0c;显著提高接收质量长按按钮执行 F 操作的功能复制快速扫描菜单中的频道名称编辑频道名称 频率显示选项扫描列表分配…

Window下如何对Redis进行开启与关闭

目录 前言1. 图文界面2. 命令行 前言 由于长期使用Linux界面&#xff0c;对于Window下的Redis&#xff0c;不知如何下手。特此记录该博文 特别注意&#xff0c;刚下载好的Redis&#xff0c;如果需要配置密码&#xff0c;可以再该文件进行配置&#xff1a;redis.windows-servi…

【Python】给出n个数,找出这n个数的最大值,最小值,和。

问题描述 给出n个数&#xff0c;找出这n个数的最大值&#xff0c;最小值&#xff0c;和。 样例输入 5 1 3 -2 4 5 Data 样例输出 5 -2 11 n int(input()) # 从用户输入中读取一个整数&#xff0c;将其赋给变量n# 从用户输入中读取一行字符串&#xff0c;使用空格分割字符串&a…

火狐挂代理访问问题Software is preventing Firefox from safely connecting to this site

1、报错 Software is preventing Firefox from safely connecting to this site2、解决步骤 火狐浏览器访问http://burp&#xff0c;右上角有下载按钮下载下来证书文件 在 Firefox 中设置证书颁发机构 (CA) 验证

共享内存的创建和映射过程

消息队列、共享内存、信号量的机制&#xff1a;它们在使用之前都要生成 key&#xff0c;然后通过 key 得到唯一的 id&#xff0c;并且都是通过 xxxget 函数。在内核里面&#xff0c;这三种进程间通信机制是使用统一的机制管理起来的&#xff0c;都叫 ipcxxx。为了维护这三种进程…

代码随想录Day51 完结篇 LeetCode T84 柱状图的最大矩形

前言 今天代码随想录一刷也告一段落了,没想到我居然坚持下来了,一节都没有落下,学习到了很多种不同的解题思路,也和大家一块交流了很多,哈哈也许不久以后我还得再次二刷代码随想录,希望这一系列的题解能给大家带来帮助,如想要系统学习,请参照代码随想录网站的题解以及b站的配套…

【Java 进阶篇】揭秘 Jackson:Java 对象转 JSON 注解的魔法

嗨&#xff0c;亲爱的同学们&#xff01;欢迎来到这篇关于 Jackson JSON 解析器中 Java 对象转 JSON 注解的详细解析指南。JSON&#xff08;JavaScript Object Notation&#xff09;是一种常用于数据交换的轻量级数据格式&#xff0c;而 Jackson 作为一款优秀的 JSON 解析库&am…

【python】--python基础学习

目录 一、基础语法二、基础数据类型1、变量赋值2、数值型3、字符串型4、列表List5、元组Tuple6、字典dictionary7、数据类型转换 三、python运算符四、条件控制与循环五、常用函数1、字符串函数2、format函数 一、基础语法 标识符是允许作为变量&#xff08;函数、类等&#x…

【C++】模板初阶 【 深入浅出理解 模板 】

模板初阶 前言&#xff1a;泛型编程一、函数模板&#xff08;一&#xff09;函数模板概念&#xff08;二&#xff09;函数模板格式&#xff08;三&#xff09;函数模板的原理&#xff08;四&#xff09;函数模板的实例化&#xff08;五&#xff09;模板参数的匹配原则 三、类模…