Redis-概论

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: [Remote Dictionary Service],也就是「远程字典服务」,Redis。

[Remote Dictionary Service],也就是「远程字典服务」,Redis。

Redis我们都知道有5种基础数据结构:分别为:string (字符串)、list (列表)、set (集合)、hash (哈希) 和 zset (有序集合)。

再说这些基础数据结构的时候,我们先说说Redis的Key:

Key:

Redis的键是二进制安全的,也就是任何binary sequence都可以作为键,比如“foo”到到JPEG文件的内容,空字符串也是有效的值,Redis的键根据自身业务去设计,但不要过于长和短,它最大大小为512MB,当然关于键的设计,官网给出了hashing的处理方式。

string:

它的数据结构是Key-Value,通过key获取相应的值。Redis 的字符串是动态字符串,是可以修改的字符串,在内存中它是以字节数组的形式存在的。

Redis 的字符串叫着「SDS」,也就是 Simple Dynamic String。它的结构是一个带长度信息的字节数组。以'\0'结尾。SDS结构使用的是范型,为什么不直接用 int 呢,这是因为当字符串比较短时,存入的值 和 分配的空间 可以使用 byte 和 short 来表示,

struct SDS<T> {  T capacity; // 数组容量 T len; // 数组长度byte flags; // 特殊标识位byte[] content; // 数组内容}

Redis 为了对内存做极致的优化,不同长度的字符串使用不同的结构体来表示。它采用预分配冗余空间的方式来减少内存的频繁分配,Redis内部当前字符串实际分配的空间一般高于字符串长度。当字符串长度小于 1M 时,扩容都是加倍现有的空间,如果超过 1M,扩容时一次只会多扩 1M 的空间,

简单操作,格式 {SET 键 值,GET 键}.当批量SETGET的时候,会节省网络耗时开销.(Redis管道机制)。

过期事件,格式{EXPIRE  键 时间}. {setex 键 时间 值}。

计数:如果 value 值是一个整数,还可以对它进行自增操作。自增是有范围的,它的范围是signed long 的最大最小值,超过了这个值,Redis 会报错。格式{incr 键}.

list:

它是链表而不是数组,插入和删除操作都是O(1)级别,但是索引慢O(n)。当列表弹出了最后一个元素之后,该数据结构自动被删除,内存被回收。

Redis 的列表结构常用来做异步队列使用。将需要延后处理的任务结构体序列化成字符串塞进 Redis 的列表,另一个线程从这个列表中轮询数据进行处理。

右边进左边出:队列  右边进右边出:栈

我们会发现,Redis底层存储是一个快速链表的结构(quicklist).首先在列表元素较少的情况下会使用一块连续的内存存储,这个结构是 ziplist,也即是压缩列表(支持双向遍历)。它将所有的元素紧挨着一起存储,分配的是一块连续的内存。当数据量比较多的时候才会改成 quicklist。ziplist是列表键和哈希键的底层实现之一。当一个列表键只包含少量列表项,并且每个列表项要么是小整数值,要么就是长度较短的字符串,那么Redis就会使用压缩列表。

image.png

这里,注意观察 debug object 输出的 encoding 字段都是 ziplist,这就表示内部采用压

缩列表结构进行存储。

struct ziplist<T> { int32 zlbytes; // 整个压缩列表占用字节数int32 zltail_offset; // 最后一个元素距离压缩列表起始位置的偏移量,用于快速定位到最后一个节点 int16 zllength; // 元素个数T[] entries; // 元素内容列表,挨个挨个紧凑存储int8 zlend; // 标志压缩列表的结束,值恒为 0xFF}

zltail_offset就是用来快速定位到最后一个元素。倒着遍历。

entry 块随着容纳的元素类型不同,也会有不一样的结构。

struct entry {int<var> prevlen; // 前一个 entry 的字节长度int<var> encoding; // 元素类型编码optional byte[] content; // 元素内容}

encoding 字段存储了元素内容的编码类型信息,ziplist 通过这个字段来决定后面的content 内容的形式、通过前缀位来识别具体存储的数据形式,content 字段在结构体中定义为 optional 类型,表示这个字段是可选的,对于很小的整数而言,它的内容已经内联到 encoding 字段的尾部了。

因为 ziplist 都是紧凑存储,没有冗余空间 (对比一下 Redis 的字符串结构)。意味着插入一个新的元素就需要调用 realloc 扩展内存。取决于内存分配器算法和当前的 ziplist 内存大小,realloc 可能会重新分配新的内存空间,并将之前的内容一次性拷贝到新的地址,也可能在原有的地址上进行扩展,这时就不需要进行旧内容的内存拷贝。如果 ziplist 占据内存太大,重新分配内存和拷贝内存就会有很大的消耗。所以 ziplist 不适合存储大型字符串,存储的元素也不宜过多

 

当 set 集合容纳的元素都是整数并且元素个数较小时,Redis 会使用 intset 来存储结合元素。intset 是紧凑的数组结构,同时支持 16 位、32 位和 64 位整数。

struct intset<T> {  int32 encoding; // 决定整数位宽是 16 位、32 位还是 64 位 int32 length; // 元素个数int<T> contents; // 整数数组,可以是 16 位、32 位和 64 位}

hash

无序字典,数组+链表二位结构。第一维 hash 的数组位置碰撞时,就会将碰撞的元素使用链表串接起来。

image.png

Set集合

它内部的键值对是无序的唯一的。它的内部实现相当于一个特殊的字典,字典中所有的 value 都是一个值 NULL。set 结构可以用来存储活动中奖的用户 ID,因为有去重功能,可以保证同一个用户不会中奖两次。

zset (有序列表)

一方面它是一个 set,保证了内部value 的唯一性,另一方面它可以给每个 value 赋予一个 score,代表这个 value 的排序权重。它的内部实现用的是一种叫着「跳跃列表」的数据结构。zset 可以用来存粉丝列表,value 值是粉丝的用户 ID,score 是关注时间。我们可以对粉丝列表按关注时间进行排序。zset 内部的排序功能是通过「跳跃列表」数据结构来实现的,它的结构非常特殊,也比较复杂。

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
2月前
|
缓存 NoSQL 应用服务中间件
Redis实战篇
Redis实战篇
|
6月前
|
存储 NoSQL Linux
Redis入门到通关之Redis5种网络模型详解
Redis入门到通关之Redis5种网络模型详解
103 1
|
存储 缓存 NoSQL
一篇吃透redis
一篇吃透redis
55 0
|
6月前
|
存储 NoSQL Redis
redis入门学习
redis入门学习
60 0
|
6月前
|
NoSQL 网络安全 Redis
Redis进阶-Redis使用建议一二事
Redis进阶-Redis使用建议一二事
34 0
|
6月前
|
存储 NoSQL Linux
【Redis入门】 —— 关于Redis的一点儿知识
【Redis入门】 —— 关于Redis的一点儿知识
|
存储 缓存 监控
一文带你吃透Redis
一文带你吃透Redis
220 0
|
存储 SQL NoSQL
Redis学习笔记(一) 初遇篇
Redis学习笔记(一) 初遇篇
Redis学习笔记(一) 初遇篇