redis数据结构详解(基本数据结构,位图,HyperLogLog,GeoHash,布隆过滤器)

本文主要是介绍redis数据结构详解(基本数据结构,位图,HyperLogLog,GeoHash,布隆过滤器),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

redis数据结构详解

文章目录

  • redis数据结构详解
  • 1. 五种基本数据结构
    • 1.1 String
    • 1.2 list
    • 1.3 hash
    • 1.4 set
    • 1.5 zset
  • 2. 高级特性
    • 2.1 位图
    • 2.2 HyperLogLog
    • 2.3 Geo Hash
    • 2.4 布隆过滤器

参考书籍: 老钱的redis深度历险

1. 五种基本数据结构

1.1 String

String是Redis最简单得数据结构,它的内部表示就是一个字符数组。
字符串结构使用比较广泛,一个常见得用途就是用来缓存用户信息,我们将用户信息使用序列化技术转换成字符串,然后将序列后得字符串放进redis来缓存。
Redis得字符串是动态字符串,是可以修改得字符串,内部结构的是西安类似于Java的ArrayList,采用预分配冗余空间的频繁。如下图所示:
在这里插入图片描述
内部为当前字符串分配的实际空间capacity一般要高于实际字符串长度len.当字符串长度小于1mb时,扩容都是加倍现有的空间,如果字符串长度超过1MB,扩容时只会多扩1MB的空间。
字符串的最大长度为512MB。
当value是一个整数时还可以进行递增递减等操作。

常用命令

#简单命令 赋值操作
set key value 
#简单命令 取值操作
get key 
#简单命令 删除操作
del key 
# 当value是整数时 ,可以使用incr或 incrby
incr/decr key  
incrby/decrby key 5  #批量写
mset k1 v1 k2 v2 k3 v3
#批量读
mget k1 k2 k3#过期时间
expire key second
#setex的使用
setex key second value#setnx 操作 如果key不存在则赋值成功,如果key存在则赋值失败返回0  (可以借助setnx实现分布式锁)
setnx key value

1.2 list

Redis中的list是一个双向链表。
所以说可以通过list构建两种数据结构:

  • FIFO队列 先进先出
  • FILO栈 先进后出

实现FIFO队列:
如果是左边推,那么就右边出
如果是右边推,那么就左边出
实现FILO栈:
如果左边推,那么左边出
如果右边推,那么就右边出

常用命令

#FIFO 队列
rpush queue 1 2 3 4 5
lpop queue 5(该数字表示弹出几个元素)#FILO 栈
rpush queue 1 2 3 4 5
rpop queue 5#根据索引获取值(获取之后并不删除,pop操作获取之后会从原先链表中删除)
# index可以为负数,为负数则表示倒数第几个
lindex key index#分页操作 
# 0 ~-1  表示获取所有元素
lrange key 0 -1

再深入一些,会发现redis底层存储的不是一个简单的linkedList,而是称之为快速链表(quicklist)的一个结构。
首先在列表元素较少的情况下,会使用一块连续的内存存储,这个结构是ziplist,既压缩列表。他将所有的元素彼此紧挨着一起存储,分配的是一块连续的内存。当数据量比较多的时候才会改成quicklist。因为普通的链表需要的附加指针空间太大,会浪费空间,还会加重内存碎片化。比如普通链表里存得知识Int类型的数据,结构上还需要两个额外的指针prev和next。 所以Redis将链表和ziplist结合起来组成quicklist,也就是将多个ziplist使用双向指针串起来使用,quicklist既满足了快速的插入删除性能,也不会出现太大的空间冗余。如下图所示:
在这里插入图片描述

1.3 hash

hash 字典其实就相当于java中的HashMap 平时开发中也可以使用hash存储java对象。

常用命令

hset key field value
hget key field

1.4 set

set 集合相当于Java语言中的HashSet, 内部的键值对是无序的,并且具有去重功能

常用命令

# 增加
sadd key member(member代表存储的元素,可以批量操作跟多个member)#获取集合所有元素
smembers key #集合长度
scard key#判断某一个元素(value)是否存在 存在返回1 否则返回0  相当于containsKey()
sismember users value #弹出一个
spop users

1.5 zset

zset可能是Redis提供的最有特色的数据结构。
它类似于Java的SoredSet和HashMap的结合体,一方面它是一个set,保证了内部value的唯一性,另一方面它给每一个value赋予一个score,代表了这个value的排序权重。内部实现是 跳跃列表的数据结构,在Java中有skipList这种的跳表实现。跳表结构: 其实就是一种分层的数据结构,将底层的数据采用硬币算法(随机0 或 1)当为0时向上衍生一层,依次类推整个数据结构,当然该数据结构具有不稳定性,只有当数据足够大的时候,才会趋近于一种平衡状态。

常用命令:

#添加元素
zadd key score value
#获取全部元素 按照score 降序排列
zrange key 0 -1 
#获取全部元素  按照score 升序排列
zrevrange key 0 -1
# 获取长度
zcard key #获取指定value的score
zscore key value

2. 高级特性

2.1 位图

位图并不是什么特殊的数据结构,它的内容其实就是普通的字符串,也就是byte数组。
我们可以使用普通的get/set直接获取和设置整个位图的内容,也可以使用位图操作getbit/setbit等将byte数组看成位数组来处理。
应用场景:
平时的开发过程中,会有一些布尔类型数据需要存取,比如签到,签了就是1,没签就是0,要记录365天,如果使用普通的key/value,每个用户要记录365个,当用户体量过大时,需要的存储空间是惊人的。
为了解决这个问题,Redis提供了位图数据结构,这样每天的签到纪录只占据一个位,365天就是365位,大约46个字节。这样就大大节约了存储空间。位图的最小单位是比特(bit)。
下面演示bitmap位图的一个零存整取的一个案例:
字符A 的ASCII码值为:65 ,转成二进制就是 0100 0001
位数组的顺序与字符数组顺序相反,也就是我们只需要在 索引1 位置和7位置设置 1 即可得到字符A

在这里插入图片描述
统计和查找
Redis提供了位图统计指令bitcount和位图查找指令bitpos。
bitcount用来统计指定范围内1的个数,bitpos用来查找指定范围内出现的第一个0或1
比如我们可以通过bitcount统计用户一共签到了多少天,通过bitpos指令查找用户从那一天开始第一次签到,如果指定了范围参数[start,end] ,就可以统计在某个时间范围内用户签到了多少天,用户自某天以后的那天开始签到。
实战
在这里插入图片描述

2.2 HyperLogLog

HyperLogLog提供不精确的去重计数方案,虽然不准确,但是也不是非常离谱,标准误差是0.81%

应用场景:
首先解释下 uv和pv
pv: 页面浏览量或点击量既页面刷新的次数,每一次页面刷新,就算做一次PV流量。
uv: 独立访客数,指访问某个站点或点击某个网页不同IP地址的人数,UV值记录第一次进入网站的具有独立IP的访问者,在同一天内多次访问则只记录一次
你有一个网站,需要统计每个网页每天的UV数据,你会如何实现呢?
如果统计PV,非常好办,每个网页配一个redis计数器就可以了,把这个计数器的key后缀加上当天的日期。这样来一个请求就incr 一下。
但是UV不同,需要去重,当然我们可以使用set集合来存储当天访问过页面的用户IP。
但是,当页面访问量非常大时,比如一个爆款页面可能有上千万的UV,那么就需要一个很大的set集合来统计,这就非常浪费空间。如果这样的页面很多,那么需要的存储空间是惊人的。
HyperLogLog就是解决这样的问题的。

实战: 统计uv value是用户id

    public static void main(String[] args) {Jedis jedis = new Jedis("127.0.0.1", 6379);for (int i = 0; i < 1000; i++) {jedis.pfadd("uv", "userid" + i);}}

在这里插入图片描述
可以看到误差是0.004
多了几个,那么它到底具备不具备去重呢?
改造代码如下

    public static void main(String[] args) {Jedis jedis = new Jedis("127.0.0.1", 6379);for (int i = 0; i < 1000; i++) {jedis.pfadd("uv", "userid" + i);}for (int i = 0; i < 10; i++) {jedis.pfadd("uv", "userid999");}}

在这里插入图片描述
可以看到pfcount还是1004,是具备去重功能的,只不过有误差.

2.3 Geo Hash

2.4 布隆过滤器

这篇关于redis数据结构详解(基本数据结构,位图,HyperLogLog,GeoHash,布隆过滤器)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

基本知识点

1、c++的输入加上ios::sync_with_stdio(false);  等价于 c的输入,读取速度会加快(但是在字符串的题里面和容易出现问题) 2、lower_bound()和upper_bound() iterator lower_bound( const key_type &key ): 返回一个迭代器,指向键值>= key的第一个元素。 iterator upper_bou

OpenHarmony鸿蒙开发( Beta5.0)无感配网详解

1、简介 无感配网是指在设备联网过程中无需输入热点相关账号信息,即可快速实现设备配网,是一种兼顾高效性、可靠性和安全性的配网方式。 2、配网原理 2.1 通信原理 手机和智能设备之间的信息传递,利用特有的NAN协议实现。利用手机和智能设备之间的WiFi 感知订阅、发布能力,实现了数字管家应用和设备之间的发现。在完成设备间的认证和响应后,即可发送相关配网数据。同时还支持与常规Sof

【数据结构】——原来排序算法搞懂这些就行,轻松拿捏

前言:快速排序的实现最重要的是找基准值,下面让我们来了解如何实现找基准值 基准值的注释:在快排的过程中,每一次我们要取一个元素作为枢纽值,以这个数字来将序列划分为两部分。 在此我们采用三数取中法,也就是取左端、中间、右端三个数,然后进行排序,将中间数作为枢纽值。 快速排序实现主框架: //快速排序 void QuickSort(int* arr, int left, int rig

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

6.1.数据结构-c/c++堆详解下篇(堆排序,TopK问题)

上篇:6.1.数据结构-c/c++模拟实现堆上篇(向下,上调整算法,建堆,增删数据)-CSDN博客 本章重点 1.使用堆来完成堆排序 2.使用堆解决TopK问题 目录 一.堆排序 1.1 思路 1.2 代码 1.3 简单测试 二.TopK问题 2.1 思路(求最小): 2.2 C语言代码(手写堆) 2.3 C++代码(使用优先级队列 priority_queue)

【IPV6从入门到起飞】5-1 IPV6+Home Assistant(搭建基本环境)

【IPV6从入门到起飞】5-1 IPV6+Home Assistant #搭建基本环境 1 背景2 docker下载 hass3 创建容器4 浏览器访问 hass5 手机APP远程访问hass6 更多玩法 1 背景 既然电脑可以IPV6入站,手机流量可以访问IPV6网络的服务,为什么不在电脑搭建Home Assistant(hass),来控制你的设备呢?@智能家居 @万物互联

K8S(Kubernetes)开源的容器编排平台安装步骤详解

K8S(Kubernetes)是一个开源的容器编排平台,用于自动化部署、扩展和管理容器化应用程序。以下是K8S容器编排平台的安装步骤、使用方式及特点的概述: 安装步骤: 安装Docker:K8S需要基于Docker来运行容器化应用程序。首先要在所有节点上安装Docker引擎。 安装Kubernetes Master:在集群中选择一台主机作为Master节点,安装K8S的控制平面组件,如AP

《数据结构(C语言版)第二版》第八章-排序(8.3-交换排序、8.4-选择排序)

8.3 交换排序 8.3.1 冒泡排序 【算法特点】 (1) 稳定排序。 (2) 可用于链式存储结构。 (3) 移动记录次数较多,算法平均时间性能比直接插入排序差。当初始记录无序,n较大时, 此算法不宜采用。 #include <stdio.h>#include <stdlib.h>#define MAXSIZE 26typedef int KeyType;typedef char In

嵌入式Openharmony系统构建与启动详解

大家好,今天主要给大家分享一下,如何构建Openharmony子系统以及系统的启动过程分解。 第一:OpenHarmony系统构建      首先熟悉一下,构建系统是一种自动化处理工具的集合,通过将源代码文件进行一系列处理,最终生成和用户可以使用的目标文件。这里的目标文件包括静态链接库文件、动态链接库文件、可执行文件、脚本文件、配置文件等。      我们在编写hellowor