Redis-五种数据类型

Redis基本特性

a) 非关系型的键值对数据库,可以根据键以O(1) 的时间复杂度取出或插入关联值

b) Redis 的数据是存在内存中的

c) 键值对中键的类型可以是字符串,整型,浮点型等,且键是唯一的

d) 键值对中的值类型可以是string,hash,list,set,sorted set 等

e) Redis 内置了复制,磁盘持久化,LUA脚本,事务,SSL, ACLs,客户端缓存,客户端代理等功能(6.0新特性)

f) 通过Redis 哨兵和Redis Cluster 模式提供高可用性

Redis应用场景

a) 计数器 可以对 String 进行自增自减运算,从而实现计数器功能。Redis 这种内存型数据库的读写性能非常高,很适合存储频繁读写的计数量。

b) 分布式ID生成 利用自增特性,一次请求一个大一点的步长如 incr 2000 ,缓存在本地使用,用完再请求。

c) 海量数据统计 位图(bitmap):存储是否参过某次活动,是否已读谋篇文章,用户是否为会员, 日活统计。

d) 会话缓存 可以使用 Redis 来统一存储多台应用服务器的会话信息。当应用服务器不再存储用户的会话信息,也就不再具有状态,一个用户可以请求任意一个应用服务器,从而更容易实现高可用性以及可伸缩性。

e) 分布式队列/阻塞队列 List 是一个双向链表,可以通过 lpush/rpushrpop/lpop 写入和读取消息。可以通过使用brpop/blpop 来实现阻塞队列。

f) 分布式锁实现 在分布式场景下,无法使用基于进程的锁来对多个节点上的进程进行同步。可以使用 Redis 自带的 SETNX 命令实现分布式锁。

g) 热点数据存储 最新评论,最新文章列表,使用list 存储,ltrim取出热点数据,删除老数据。

h) 社交类需求 Set 可以实现交集,从而实现共同好友等功能,Set通过求差集,可以进行好友推荐,文章推荐。

i) 排行榜 sorted_set可以实现有序性操作,从而实现排行榜等功能。

j) 延迟队列 使用sorted_set,使用 【当前时间戳 + 需要延迟的时长】做score, 消息内容作为元素,调用zadd来生产消息,消费者使用zrangbyscore获取当前时间之前的数据做轮询处理。消费完再删除任务 rem key member

Redis 的key 都是字符串(SDS, simple dynamic string)类型,命令由客户端发送给服务端都会转换为字节流的形式,虽然看起来可能是数字、浮点数、或者字符串多种类型

> set 1 a // 数字key
> get 1> set 0.5 b // 浮点key
> get 0.5> set a c // 字符串key
> get a以上key 发送到服务端最终都是以字节流的形式

SDS 的特点:

a)二进制安全的数据结构,安全体现在不会丢数据(c:char data[]="g\0ao",C 语言以"\0" 作为字符串结尾标记,业务数据存在"\0"时存在安全问题)

b)内存预分配机制,防止频繁扩容产生的内存分配问题

c)兼容C语言的函数库

扩容示例:

redis:sds:free: 0len: 3char buf[]="gao" -> "gao123"len: 3addlen: 3(len + addlen) * 2 = 12  //扩容,(现有长度+需要增加长度)*2// 成倍扩容,当长度len=1024,再扩容每次增加1M,(所以使用 setbit 设置大点的空间,防止频繁扩容)append,setbit sds:free: 6len: 6char buf[]="gao123"  

设计思想:

K-V:map -> dict,
数据库:海量数据的存储
1、数组:O(1) 随机访问,下表
2、链表:O(n) 头结点,遍历
3、数:log(n) 优化的比较好的场景,二分查找hash(key) 任意数据进行随机散列,并且把hash 值转换为一个自然数[大]
创建一个大的数组:arr[4]
hash(key) -> 自然数[大] % 4 = [0, arr.size-1], redis 就是这么干的
1、任意相同的输入,一定能得到相同的输出
2、不同的输入,可能得到相同的输出
把现实中无限的数据放到有限的集合中,肯定会产生hash 冲突    
(k1,v1),(k2,v2),(k3,v3)hash(k1) % 4 = 0
hash(k2) % 4 = 1arr[0]->(k1,v1,next->null)
arr[1]->(k3,v3,next->k2)(k2,v2,next->null)
产生hash 冲突时,redis 使用的是头插法
redis 是比较基础的语言,没有那么多高级特性,没有那么多工具可以用,是redis 作者自己实现的
通过链表法来解决碰撞,java 中的hashMap 要复杂得多key:string
value:string,hash,list,set,sorted set

Redis之String 类型数据结构直通车

Redis6.0 多线程,但是最终执行用户请求是在单线程中进行的,渐进式扩容很有必要

有趣命令:

> type [key] //查看key的类型
string
> object encoding 100 //key 所对应的值,在redis 底层是一个什么样的编码格式
"int"
> object encoding str
"embstr"
> object encoding 0.1
"int"int / embstr 都是redis 对内存方面的优化

Redis求模小优化:

任意数 % 2^n //对CPU 不友好,累除法
任意数 & (2^n - 1) //一次位运算

Redis 对于值是string 类型的底层编码结构分析:

//type [key],查看key 的类型
//object encoding [key],查值在底层的编码格式//redis 中所有对象的封装
typedef struct redisObject {    unsigned type:4; //约束客户端命令,当前类型。位域的语法,占4个bit 位unsigned encoding:4; //编码格式,同样占4个bit 位unsigned lru:LRU_BITS; //24个bit 位,也就是3 个字节int refcount; //引用计数法,4个字节void *ptr; //数据真正存放的位置,8个字节
} robj;redisObject 占16个字节的空间
cache line:64字节,64 - 16 = 48 字节,肯定可以利用起来
48个字节使用sdshdr8的数据结构存储,因为48在数据范围 2^5 ~ 2^8-1 之间struct __attribute__ ((__packed__)) sdshdr8 {  // 表示 2^5 ~ 2^8-1 的数据    uint8_t len; /* used */    uint8_t alloc; /* excluding the header and null terminator */    unsigned char flags; /* 3 lsb of type, 5 unused bits */    char buf[];
};sds本身消耗4个字节,其中len、alloc、flags各占一个字节,另外'\0'占一个字节,因为兼容C语言的函数库
最终:48 - 4 = 44 字节,用来存放实际的数据

对于string 类型的value 有结论如下:

value 值是string 类型的底层编码结构:
1、value值的长度小于等于20,尝试转换成数字转换成功,底层使用int 编码格式
2、value值不满足条件1,且长度小于等于44redis 底层使用embstr 编码结构
3、value值不满足1和2条件,使用row 编码结构也就是sds 的数据结构,简单动态字符串

扩展分析:

亿级日活的统计:bit 的特点,除了0 就是1,所以可以用1个bit 位表示登陆状态
像这样1个字节就可以表示8个用户1 1 0 1 0 1 0 1 1 1 0 1 0 0 1 0 1   -- 登陆状态
offset:0 1 2 3 4 5 6 7 8 9 ...命令:setbit key offset 0|1   
日期可以作为一个key 使用,“2022-5-26”变种:userId 是数字时,可以作为偏移量使用
setbit a-bit-map userId 1
setbit a-bit-map userId 1getbit a-bit-map 8
userId:
bit: 0/1 (默认值是0)

简单测试:

> setbit login_05_26 100 1
> setbit login_05_26 100 1
> setbit login_05_26 100 1> getbit login_05_26 100  //获取日期5月26日用户100的活跃状态,id特别大可以减固定值优化> setbit login_05_26 100 0 //恢复状态
> getbit login_05_26 100> STRLEN login_05_26 //长度13 字节。100/8bit = 12.5 所以分配13个字节
> type login_05_26 //string 类型的数据
> get login_05_26 //可以执行命令,获取的数据是内存中的存储,没有实际意义> setbit login_05_26 100 1
> setbit login_05_26 101 1
> setbit login_05_26 102 1
> setbit login_05_26 103 1> BITCOUNT login_05_26 //统计bit位是1的个数:4
> strlen login_05_26 //13个字节
> BITCOUNT login_05_26 0 12 //一共13个字节,从索引0开始,所以是0和12。可以统计一部分数据根据索引string 表示数据最大是512M,索引位是2^32-1。最多可表示这么多的用户

另一个扩展分析:

login_05_26: 0 1 0 1 0 1 1 1 0 1 0 1 1 0 0 1 1
login_05_27: 1 1 0 1 0 1 0 1 1 1 0 1 0 0 1 0 1
连续登陆情况:按位与再统计
> BITOP and login_05_26-27 login_05_26 login_05_27 //按位与操作,结果存到login_05_26-27中
> BITCOUNT login_05_26-27 //再做一次bitcount可以得到连续登陆的结果login_05_24: 0 1 0 1 0 1 1 1 0 1 0 1 1 0 0 1 1
login_05_25: 1 1 0 1 0 1 0 1 1 1 0 1 0 0 1 0 1
login_05_26: 0 1 0 1 0 1 1 1 0 1 0 1 1 0 0 1 1
login_05_27: 1 1 0 1 0 1 0 1 1 1 0 1 0 0 1 0 1
login_05_28: 0 1 0 1 0 1 1 1 0 1 0 1 1 0 0 1 1
login_05_29: 1 1 0 1 0 1 0 1 1 1 0 1 0 0 1 0 1
login_05_30: 0 1 0 1 0 1 1 1 0 1 0 1 1 0 0 1 1
周活:按位或,有一天登陆就行
> BITOP or login_05_26-27-active login_05_26 login_05_27 //两天内有一天登陆就行
> BITCOUNT login_05_26-27-activeredis 源码有判断只能是0或1,按位与 按位或,效率非常高
汉明重量 按位操作 有兴趣的同学可以了解

List常用API

/> help @listLPUSH key element [element ...]
RPOP key
RPUSH key element [element ...]
LPOP key
BLPOP key [key ...] timeout
BRPOP key [key ...] timeout
BRPOPLPUSH source destination timeout
RPOPLPUSH  source destination
LINDEX key index
LLEN key
LINSERT key BEFORE|AFTER pivot element
LRANGE key start stop
LREM key count element
LSET key index element
LTRIM key start stop 

List是一个有序(按加入的时序排序)的数据结构,Redis采用quicklist(双端链表) 和 ziplist 作为List的底层实现。

可以通过设置每个ziplist的最大容量,quicklist的数据压缩范围,提升数据存取效率

list-max-ziplist-size  -2        //  单个ziplist节点最大能存储  8kb  ,超过则进行分裂,将数据存储在新的ziplist节点中
list-compress-depth  1        //  0 代表所有节点,都不进行压缩,1, 代表从头节点往后走一个,尾节点往前走一个不用压缩,其他的全部压缩,2,3,4 ... 以此类推

Redis - quicklist 数据结构:

Redis - ziplist 数据结构:

Hash常用API

/> help  @hash HSET key field value [field value ...]
HGET key field
HMGET key field [field ...]
HKEYS key
HGETALL key
HVALS key
HEXISTS key field
HDEL key field [field ...]
HINCRBY key field increment
HINCRBYFLOAT key field increment
HLEN key
HSCAN key cursor [MATCH pattern] [COUNT count]
HSETNX key field value
HSTRLEN key field 

Hash 数据结构底层实现为一个字典( dict ),也是RedisBb用来存储K-V的数据结构,当数据量比较小,或者单个元素比较小时,底层用ziplist存储,数据大小和元素数量阈值可以通过如下参数设置。

hash-max-ziplist-entries  512    //  ziplist 元素个数超过 512 ,将改为hashtable编码 
hash-max-ziplist-value    64      //  单个元素大小超过 64 byte时,将改为hashtable编码

Redis - hash 数据结构:

Set常用API

/> help  @setSADD key member [member ...]              
SCARD key                                                 
SISMEMBER key member
SPOP key [count]
SDIFF key [key ...]
SINTER key [key ...]
SUNION key [key ...]
SMEMBERS key
SRANDMEMBER key [count]
SREM key member [member ...]
SMOVE source destination member
SUNIONSTORE destination key [key ...]
SDIFFSTORE destination key [key ...]
SINTERSTORE destination key [key ...]
SSCAN key cursor [MATCH pattern] [COUNT count] 

Set 为无序的,自动去重的集合数据类型,Set 数据结构底层实现为一个value 为 null 的 字典( dict ),当数据可以用整形表示时,Set集合将被编码为intset数据结构。两个条件任意满足时 Set将用hashtable存储数据。1, 元素个数大于 set-max-intset-entries , 2 , 元素无法用整形表示

set-max-intset-entries 512       // intset 能存储的最大元素个数,超过则用hashtable编码

Redis - set 数据结构:

ZSet常用API

/> help  @sorted_setZADD key [NX|XX] [CH] [INCR] score member [score member ...]
ZCARD key
ZCOUNT key min max
ZINCRBY key increment member
ZRANGE key start stop [WITHSCORES]
ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]
ZRANK key member
ZREM key member [member ...]
ZREMRANGEBYRANK key start stop
ZREMRANGEBYSCORE key min max
ZREVRANGE key start stop [WITHSCORES]
ZREVRANGEBYSCORE key max min [WITHSCORES] [LIMIT offset count]
ZREVRANK key member
ZSCAN key cursor [MATCH pattern] [COUNT count]
ZSCORE key member

ZSet 为有序的,自动去重的集合数据类型,ZSet 数据结构底层实现为 字典(dict) + 跳表(skiplist) ,当数据比较少时,用ziplist编码结构存储。

zset-max-ziplist-entries  128    // 元素个数超过128 ,将用skiplist编码
zset-max-ziplist-value     64     //  单个元素大小超过 64 byte, 将用 skiplist编码

Redis - zset 数据结构:

Redis - skiplist 数据结构:

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

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

相关文章

「torch.cosine_smilarity() = 0」引发的关于cpu与gpu精度问题的探讨

前言:2023年11月21日下午16:00 许,本篇博客记录由「torch.cosine_smilarity()计算余弦相似度计算结果为0」现象引发的关于 CPU 与 GPU 计算精度的探索。 事情的起因是,本人在使用 torch.cosine_smilarity() 函数计算GPU上两个特征的余弦相似度…

【迅搜02】究竟什么是搜索引擎?正式介绍XunSearch

究竟什么是搜索引擎?正式介绍XunSearch 啥?还要单独讲一下啥是搜索引擎?不就是百度、Google嘛,这玩意天天用,还轮的到你来说? 额,好吧,虽然大家天天都在用,但是我发现&am…

移远通信推出六款新型天线,为物联网客户带来更丰富的产品选择

近日,移远通信重磅推出六款新型天线,覆盖5G、非地面网络(NTN)等多种新技术,将为物联网终端等产品带来全新功能和更强大的连接性能。 移远通信COO张栋表示:“当前,物联网应用除了需要高性能的天线…

【libGDX】使用Mesh绘制三角形

1 Mesh 和 ShaderProgram 简介 1.1 创建 Mesh 1)Mesh 的构造方法 public Mesh(boolean isStatic, int maxVertices, int maxIndices, VertexAttribute... attributes) public Mesh(boolean isStatic, int maxVertices, int maxIndices, VertexAttributes attribut…

js ::after简单实战

::after的作用是在元素后面再加个XXX样式 工作中遇到了一个表格,鼠标指到单元格要有个整行编辑态的效果,下面写个简单的demo 有人可能会说了,直接修改某个单元格的hover样式不就行了嘛,问题是如果鼠标指到单元格和单元格直接的…

Android DatePicker(日期选择器)、TimePicker(时间选择器)、CalendarView(日历视图)- 简单应用

示意图&#xff1a; layout布局文件&#xff1a;xml <?xml version"1.0" encoding"utf-8"?> <ScrollView xmlns:android"http://schemas.android.com/apk/res/android"xmlns:app"http://schemas.android.com/apk/res-auto"…

实验过程中的问题记录

代码&#xff1a; if args.local_rank in [-1, 0] and eval_dataset is not None and args.eval_steps > 0 and global_step % args.eval_steps 0 :metric_cur eval_fn(args, eval_dataset, model, tokenizer, global_stepglobal_step, file_prefix"eval_")当参…

IP-guard Web系统远程命令执行漏洞说明

一、漏洞说明 近期收到反馈,IP-guard Web服务器存在远程命令执行漏洞(RCE),经过分析,确认是因为Web系统的申请审批功能使用了开源插件 flexpaper 实现文件在线预览功能,此插件存在远程代码执行漏洞。 攻击者可利用 flexpaper插件漏洞,在文件预览参数中拼接其它恶意命令…

时序预测 | Pytorch实现TCN-Transformer的时间序列预测

时序预测 | Pytorch实现TCN-Transformer的时间序列预测 目录 时序预测 | Pytorch实现TCN-Transformer的时间序列预测效果一览基本介绍程序设计 效果一览 基本介绍 基于TCN-Transformer模型的时间序列预测&#xff0c;可以用于做光伏发电功率预测&#xff0c;风速预测&#xff0…

管理体系标准

管理体系标准 什么是管理体系&#xff1f; 管理体系是组织管理其业务的相互关联部分以实现其目标的方式。这些目标可能涉及许多不同的主题&#xff0c;包括产品或服务质量、运营效率、环境绩效、工作场所的健康和安全等等。 系统的复杂程度取决于每个组织的具体情况。对于某…

Vue2+Vue3

文章目录 第 1 章&#xff1a;Vue 核心1、 Vue 简介1.官网2.介绍与描述3. Vue 的特点4. 与其它 JS 框架的关联5. Vue 周边库 2、初始Vue3、模板语法1、Vue模板语法有2大类:2、插值语法和指令语法 4、数据绑定1. 单向数据绑定2. 双向数据绑定 5、el与data的两种写法1.e1有2种写法…

社会媒体营销提问常用的ChatGPT通用提示词模板

如何制定有效的社会媒体营销策略&#xff1f; 如何选择适合的社会媒体平台进行营销&#xff1f; 如何创造有吸引力的社会媒体内容&#xff0c;提高用户参与度和分享率&#xff1f; 如何运用社交媒体广告来增加品牌曝光和用户转化&#xff1f; 如何建立和维护社交媒体账号和…

外部 prometheus监控k8s集群资源

prometheus监控k8s集群资源 一&#xff0c;通过CADvisior 监控pod的资源状态1.1 授权外边用户可以访问prometheus接口。1.2 获取token保存1.3 配置prometheus.yml 启动并查看状态1.4 Grafana 导入仪表盘 二&#xff0c;通过kube-state-metrics 监控k8s资源状态2.1 部署 kube-st…

【科技素养】蓝桥杯STEMA 科技素养组模拟练习试卷01

单选题 1、生活中&#xff0c;我们经常说“有机蔬菜”相比普通蔬菜更加健康&#xff0c;这是因为 A、它们没有使用无机肥料 B、它们是有机的 C、它们没有使用肥料 D、人们对蔬菜的错误认知 答案&#xff1a;A 2、甲乙两位工人一起在工厂工作。甲的生产速度是每小时6个鼠标…

网络运维与网络安全 学习笔记2023.11.21

网络运维与网络安全 学习笔记 第二十二天 今日目标 端口隔离原理与配置、路由原理和配置、配置多路由器静态路由 配置默认路由、VLAN间通信之路由器 端口隔离原理与配置 端口隔离概述 实现报文之间的2层隔离&#xff0c;除了使用VLAN技术以后&#xff0c;还可以使用端口隔…

c语言:十进制转任意进制

思路&#xff1a;如十进制转二进制 就是不断除二求余在除二求余&#xff0c;然后将余数从下到写出来&#xff0c;这样&#xff0c;10011100就是156的二进制 这里举例一个六进制的代码&#xff1a; #define _CRT_SECURE_NO_WARNINGS #include<stdio.h>int main() {int …

opencv-简单图像处理

图像像素存储形式  对于只有黑白颜色的灰度图&#xff0c;为单通道&#xff0c;一个像素块对应矩阵中一个数字&#xff0c;数值为0到255, 其中0表示最暗&#xff08;黑色&#xff09; &#xff0c;255表示最亮&#xff08;白色&#xff09; 对于采用RGB模式的彩色图片&#…

「MACOS限定」 如何将文件上传到GitHub仓库

介绍 本期讲解&#xff1a;如何在苹果电脑上上传文件到github远程仓库 注&#xff1a;写的很详细 方便我的朋友可以看懂操作步骤 第一步 在电脑上创建一个新目录&#xff08;文件夹&#xff09; 注&#xff1a;创建GitHub账号、新建github仓库、git下载的步骤这里就不过多赘…

118.184.158.111德迅云安全浅谈如何避免网络钓鱼攻击

随着互联网的不断发展&#xff0c;网络钓鱼攻击也越来越猖獗&#xff0c;给个人和企业带来了巨大的经济损失和安全威胁。本文对如何防范网络钓鱼攻击提出的一些小建议 希望对大家有所帮助。 1.防止XSS&#xff08;跨站脚本攻击&#xff09;攻击 XSS攻击指的是攻击者在网站中注入…

html手势密码解锁插件(附源码)

文章目录 1.设计来源1.1 界面效果 2.效果和源码2.1 动态效果2.2 源代码 源码下载 作者&#xff1a;xcLeigh 文章地址&#xff1a;https://blog.csdn.net/weixin_43151418/article/details/134534785 html手势密码解锁插件(附源码)&#xff0c;仿手机手势密码&#xff0c;拖动九…