一、9种数据类型
概述
咱们先通过一张图理解下 Redis 外部内存治理中是如何形容这些不同数据类型的:
首先Redis外部应用一个redisObject对象来示意所有的key和value,redisObject最次要的信息如上图所示:type代表一个value对象具体是何种数据类型,encoding是不同数据类型在redis外部的存储形式。
redis反对丰盛的数据类型,不同的场景应用适合的数据类型能够无效的优化内存数据的寄存空间:
- string:最根本的数据类型,二进制平安的字符串,最大512M。
- list:依照增加程序放弃程序的字符串列表。
- set:无序的字符串汇合,不存在反复的元素。
- sorted set:已排序的字符串汇合。
- hash:key-value对的一种汇合。
- bitmap:更细化的一种操作,以bit为单位。
- hyperloglog:基于概率的数据结构。 # 2.8.9新增
- Geo:地理位置信息储存起来, 并对这些信息进行操作 # 3.2新增
- 流(Stream)# 5.0新增
String 字符串
常用命令:
setnx,set,get,decr,incr,mget 等。
利用场景:
字符串是最罕用的数据类型,他可能存储任何类型的字符串,当然也包含二进制、JSON化的对象、甚至是Base64编码之后的图片。在Redis中一个字符串最大的容量为512MB,能够说是无所不能了。redis的key和string类型value限度均为512MB。
- 缓存,热点数据
- 分布式session
- 分布式锁
- INCR计数器
- 文章的浏览量,微博点赞数,容许肯定的提早,先写入 Redis 再定时同步到数据库
全局ID
INT 类型,INCRBY,利用原子性
- INCR 限流
以访问者的 IP 和其余信息作为 key,拜访一次减少一次计数,超过次数则返回 false。 setbit 位操作
外部编码:
- int:8 个字节的长整型(long,2^63-1)
- embstr:小于等于44个字节的字符串,embstr格局的SDS(Simple Dynamic String)
- raw:SDS大于 44 个字节的字符串
redis 为什么要本人写一个SDS的数据类型,次要是为了解决C语言 char[] 的四个问题
- 字符数组必须先给指标变量调配足够的空间,否则可能会溢出
- 查问字符数组长度 工夫复杂度O(n)
- 长度变动,须要从新分配内存
- 通过从字符串开始到结尾碰到的第一个\0来标记字符串的完结,因而不能保留图片、音频、视频、压缩文件等二进制(bytes)保留的内容,二进制不平安
redis SDS
- 不必放心内存溢出问题,如果须要会对 SDS 进行扩容
- 因为定义了 len 属性,查问数组长度工夫复杂度O(1) 固定长度
- 空间预调配,惰性空间开释
- 依据长度 len来判断是完结,而不是 \0
Hash 哈希表
常用命令:
hget,hsetnx,hset,hvals,hgetall,hmset,hmget 等。
利用场景:
咱们简略举个实例来形容下 Hash 的利用场景,比方咱们要存储一个用户信息对象数据,蕴含以下信息:用户 ID 为查找的 key,存储的 value 用户对象蕴含姓名,年龄,生日等
外部编码:
- ziplist(压缩列表):当哈希类型中元素个数小于 hash-max-ziplist-entries 配置(默认 512 个),同时所有值都小于 hash-max-ziplist-value 配置(默认 64 字节)时,Redis 会应用 ziplist 作为哈希的外部实现。
- hashtable(哈希表):当上述条件不满足时,Redis 则会采纳 hashtable 作为哈希的外部实现。
List 列表
常用命令:
lpush,rpush,lpop,rpop,lrange等。
列表(list)用来存储多个有序的字符串,每个字符串称为元素;一个列表能够存储2^32-1个元素。Redis中的列表反对两端插入和弹出,并能够取得指定地位(或范畴)的元素,能够充当数组、队列、栈等
利用场景
比方 twitter 的关注列表,粉丝列表等都能够用 Redis 的 list 构造来实现,能够利用lrange命令,做基于Redis的分页性能,性能极佳,用户体验好。
音讯队列
列表类型能够应用 rpush 实现先进先出的性能,同时又能够应用 lpop 轻松的弹出(查问并删除)第一个元素,所以列表类型能够用来实现音讯队列
发红包的场景
在发红包的场景中,假如发一个10元,10个红包,须要保障抢红包的人不会多抢到,也不会少抢到.
上面咱们通过下图来看一下 Redis 中列表类型的插入和弹出操作:
上面咱们看一下 Redis 中列表类型的获取与删除操作:
Redis 列表类型的特点如下:
- 列表中所有的元素都是有序的,所以它们是能够通过索引获取的lindex 命令。并且在 Redis 中列表类型的索引是从 0 开始的。
- 列表中的元素是能够反复的,也就是说在 Redis 列表类型中,能够保留同名元素
外部编码:
- ziplist(压缩列表):当列表中元素个数小于 512(默认)个,并且列表中每个元素的值都小于 64(默认)个字节时,Redis 会抉择用 ziplist 来作为列表的外部实现以缩小内存的应用。当然上述默认值也能够通过相干参数批改:list-max-ziplist-entried(元素个数)、list-max-ziplist-value(元素值)。
- linkedlist(链表):当列表类型无奈满足 ziplist 条件时,Redis 会抉择用 linkedlist 作为列表的外部实现。
Set 汇合
常用命令:
sadd,spop,smembers,sunion,scard,sscan,sismember等。
利用场景:
Redis set 对外提供的性能与 list 相似是一个列表的性能,非凡之处在于 set 是能够主动排重的,当你须要存储一个列表数据,又不心愿呈现反复数据时,set 是一个很好的抉择,并且 set 提供了判断某个成员是否在一个 set 汇合内的重要接口,这个也是 list 所不能提供的。
1.知乎点赞数
2.存储社交关系
用户(编号user001)关注
sadd focus:user001 user003
sadd focus:user002 user003 user004
互相关注
sadd focus:user001 user002
sadd focus:user002 user001
实现形式:
set 的外部实现是一个 value 永远为 null 的 HashMap,理论就是通过计算 hash 的形式来疾速排重的,这也是 set 能提供判断一个成员是否在汇合内的起因。
Redis 中的汇合类型,也就是 set。在 Redis 中 set 也是能够保留多个字符串的,常常有人会分不清 list 与 set,上面咱们重点介绍一下它们之间的不同:
set 中的元素是不能够反复的,而 list 是能够保留反复元素的。set 中的元素是无序的,而 list 中的元素是有序的。set 中的元素不能通过索引下标获取元素,而 list 中的元素则能够通过索引下标获取元素。除此之外 set 还反对更高级的性能,例如多个 set 取交加、并集、差集等
外部编码
- intset(整数汇合):当汇合中的元素都是整数,并且汇合中的元素个数小于 512 个时,Redis 会选用 intset 作为底层外部实现。
- hashtable(哈希表):当上述条件不满足时,Redis 会采纳 hashtable 作为底层实现。
备注:咱们能够通过 set-max-intset-entries 参数来设置上述中的默认参数。
Sorted set 有序汇合
常用命令:
zadd,zrange,zrem,zcard,zscore,zcount,zlexcount等
上面先看一下列表、汇合、有序汇合三种数据类型之间的区别:
外部编码:
- ziplist(压缩列表):当有序汇合的元素个数小于 128 个(默认设置),同时每个元素的值都小于 64 字节(默认设置),Redis 会采纳 ziplist 作为有序汇合的外部实现。
- skiplist(跳跃表):当上述条件不满足时,Redis 会采纳 skiplist 作为外部编码。
备注:上述中的默认值,也能够通过以下参数设置:zset-max-ziplist-entries 和 zset-max-ziplist-value。
利用场景
Redis sorted set 的应用场景与 set 相似,区别是 set 不是主动有序的,而 sorted set 能够通过用户额定提供一个优先级(score)的参数来为成员排序,并且是插入有序的,即主动排序。当你须要一个有序的并且不反复的汇合列表,那么能够抉择 sorted set 数据结构,比方 twitter 的 public timeline 能够以发表工夫作为 score 来存储,这样获取时就是主动按工夫排好序的。点击数做出排行榜。
1.商品的评估标签,能够记录商品的标签,统计标签次数,减少标签次数,按标签的分值进行排序
BitMap 位图
在利用场景中,有一些数据只有两个属性,比方是否是学生,是否是党员等等,对于这些数据,最节约内存的形式就是用bit去记录,以是否是学生为例,1代表是学生,0代表不是学生。那么1000110就代表7集体中3个是学生,这就是BitMaps的存储需要。Bitmaps是一个能够对位进行操作的字符串,咱们能够把Bitmaps设想成是一串二进制数字,每个地位只存储0和1。下标是Bitmaps的偏移量。BitMap 就是通过一个 bit 位来示意某个元素对应的值或者状态, 其中的 key 就是对应元素自身,实际上底层也是通过对字符串的操作来实现。Redis从2.2.0版本开始新增了setbit,getbit,bitcount等几个bitmap相干命令。尽管是新命令,然而并没有新增新的数据类型,因为setbit等命令只不过是在set上的扩大。
应用场景
1.用户签到
很多网站都提供了签到性能(这里不思考数据落地事宜),并且须要展现最近一个月的签到状况
2.统计沉闷用户
应用工夫作为cacheKey,而后用户ID为offset,如果当日沉闷过就设置为1
那么我该如果计算某几天/月/年的沉闷用户呢(暂且约定,统计工夫内只有有一天在线就称为沉闷),有请下一个redis的命令
命令 BITOP operation destkey key [key ...]
阐明:对一个或多个保留二进制位的字符串 key 进行位元操作,并将后果保留到 destkey 上。
阐明:BITOP 命令反对 AND 、 OR 、 NOT 、 XOR 这四种操作中的任意一种参数
3.用户在线状态
前段时间开发一个我的项目,对方给我提供了一个查问以后用户是否在线的接口。不理解对方是怎么做的,本人思考了一下,应用bitmap是一个节约空间效率又高的一种办法,只须要一个key,而后用户ID为offset,如果在线就设置为1,不在线就设置为0,和下面的场景一样,5000W用户只须要6MB的空间。
外部编码
这个就是Redis实现的BloomFilter,BloomFilter非常简单,如下图所示,假如曾经有3个元素a、b和c,别离通过3个hash算法h1()、h2()和h2()计算而后对一个bit进行赋值,接下来假如须要判断d是否曾经存在,那么也须要应用3个hash算法h1()、h2()和h2()对d进行计算,而后失去3个bit的值,恰好这3个bit的值为1,这就可能阐明:d可能存在汇合中。再判断e,因为h1(e)算进去的bit之前的值是0,那么阐明:e肯定不存在汇合中:
须要阐明的是,bitmap并不是一种实在的数据结构,它实质上是String数据结构,只不过操作的粒度变成了位,即bit。因为String类型最大长度为512MB,所以bitmap最多能够存储2^32个bit。
HyperLogLog 基数统计、Geo 地理位置、Streams 流(5.5引入)
这三种不罕用,后续再讲