美文网首页我爱编程
redis 学习笔记

redis 学习笔记

作者: 码农老K | 来源:发表于2017-10-31 22:16 被阅读0次

这篇 redis 学习笔记主要介绍 redis 的数据结构和数据类型,并讨论数据结构的选择以及应用场景的优化。

redis 是什么?

Redis是一种面向“键/值”对类型数据的分布式NoSQL数据库系统,特点是高性能,持久存储,适应高并发的应用场景。

Redis 数据结构

动态字符串 (Sds)

双端列表 (LINKEDLIST)

字典

跳跃表 (SKIPLIST)

整数集合 (INTSET)

压缩列表 (ZIPLIST)

动态字符串

Sds (Simple Dynamic String,简单动态字符串)是 Redis 底层所使用的字符串表示,它被用 在几乎所有的 Redis 模块中

Redis 是一个键值对数据库(key-value DB),数据库的值可以是字符串、集合、列表等多种类 型的对象,而数据库的键则总是字符串对象

在 Redis 中, 一个字符串对象除了可以保存字符串值之外,还可以保存 long 类型的值当字符串对象保存的是字符串时,它包含的才是 sds 值,否则的话,它就 是一个 long 类型的值

动态字符串主要有两个作用:

实现字符串对象(StringObject)

在 Redis 程序内部用作 char * 类型的替代品

双端列表

双端链表还是 Redis 列表类型的底层实现之一,当对列表类型的键进行操作——比如执行 RPUSH 、LPOP 或 LLEN 等命令时,程序在底层操作的可能就是双端链表

双端链表主要有两个作用:

作为 Redis 列表类型的底层实现之一;

作为通用数据结构,被其他功能模块所使用;

字典

字典(dictionary),又名映射(map)或关联数组(associative array), 它是一种抽象数据结 构,由一集键值对(key-value pairs)组成,各个键值对的键各不相同,程序可以将新的键值对 添加到字典中,或者基于键进行查找、更新或删除等操作

字典的应用

实现数据库键空间(key space);

用作 Hash 类型键的其中一种底层实现;

Redis 是一个键值对数据库,数据库中的键值对就由字典保存:每个数据库都有一个与之相对应的字典,这个字典被称之为键空间(key space)。

Redis 的 Hash 类型键使用字典和压缩列表两种数据结构作为底层实现

跳跃表

跳跃表(skiplist)是一种随机化的数据,由 William Pugh 在论文《Skip lists: a probabilistic alternative to balanced trees》中提出,这种数据结构以有序的方式在层次化的链表中保存元素,它的效率可以和平衡树媲美——查找、删除、添加等操作都可以在对数期望时间下完成, 并且比起平衡树来说,跳跃表的实现要简单直观得多

和字典、链表或者字符串这几种在 Redis 中大量使用的数据结构不同,跳跃表在 Redis 的唯一作用,就是实现有序集数据类型

跳跃表将指向有序集的 score 值和 member 域的指针作为元素,并以 score 值为索引,对有序集元素进行排序。

整数集合

整数集合(intset)用于有序、无重复地保存多个整数值,它会根据元素的值,自动选择该用什么长度的整数类型来保存元素

Intset 是集合键的底层实现之一,如果一个集合:

只保存着整数元素;

元素的数量不多;

那么 Redis 就会使用 intset 来保存集合元素。

压缩列表

Ziplist 是由一系列特殊编码的内存块构成的列表,一个 ziplist 可以包含多个节点(entry),每个节点可以保存一个长度受限的字符数组(不以 0 结尾的 char 数组)或者整数

Redis 数据类型

RedisObject

redisObject 是 Redis 类型系统的核心,数据库中的每个键、值,以及 Redis 本身处理的参数,都表示为这种数据类型

redisObject 的定义位于 redis.h :

/*

* Redis 对象

*/

typedef struct redisObject {

// 类型

unsigned type:4;

// 对齐位

unsigned notused:2;

// 编码方式

unsigned encoding:4;

// LRU 时间(相对于 server.lruclock)

unsigned lru:22;

// 引用计数

int refcount;

// 指向对象的值

void *ptr;

} robj;

type 、encoding 和 ptr 是最重要的三个属性。

type 记录了对象所保存的值的类型,它的值可能是以下常量的其中一个

/*

* 对象类型

*/

#define REDIS_STRING 0 // 字符串

#define REDIS_LIST 1 // 列表

#define REDIS_SET 2 // 集合

#define REDIS_ZSET 3 // 有序集

#define REDIS_HASH 4 // 哈希表

encoding 记录了对象所保存的值的编码,它的值可能是以下常量的其中一个

/*

* 对象编码

*/

#define REDIS_ENCODING_RAW 0 // 编码为字符串

#define REDIS_ENCODING_INT 1 // 编码为整数

#define REDIS_ENCODING_HT 2 // 编码为哈希表

#define REDIS_ENCODING_ZIPMAP 3 // 编码为 zipmap(2.6 后不再使用)

#define REDIS_ENCODING_LINKEDLIST 4 // 编码为双端链表

#define REDIS_ENCODING_ZIPLIST 5 // 编码为压缩列表

#define REDIS_ENCODING_INTSET 6 // 编码为整数集合

#define REDIS_ENCODING_SKIPLIST 7 // 编码为跳跃表

ptr 是一个指针,指向实际保存值的数据结构,这个数据结构由 type 属性和 encoding 属性决定。

当执行一个处理数据类型的命令时,Redis 执行以下步骤:

根据给定key,在数据库字典中查找和它像对应的redisObject,如果没找到,就返回 NULL 。

检查redisObject的type属性和执行命令所需的类型是否相符,如果不相符,返回类 型错误。

根据redisObject的encoding属性所指定的编码,选择合适的操作函数来处理底层的 数据结构。

返回数据结构的操作结果作为命令的返回值。

字符串

REDIS_STRING (字符串)是 Redis 使用得最为广泛的数据类型,它除了是 SET 、GET 等命令 的操作对象之外,数据库中的所有键,以及执行命令时提供给 Redis 的参数,都是用这种类型 保存的。

字符串类型分别使用 REDIS_ENCODING_INT 和 REDIS_ENCODING_RAW 两种编码

只有能表示为 long 类型的值,才会以整数的形式保存,其他类型 的整数、小数和字符串,都是用 sdshdr 结构来保存

哈希表

REDIS_HASH (哈希表)是HSET 、HLEN 等命令的操作对象

它使用 REDIS_ENCODING_ZIPLIST和REDIS_ENCODING_HT 两种编码方式

Redis 中每个hash可以存储232-1键值对(40多亿)

列表

REDIS_LIST(列表)是LPUSH 、LRANGE等命令的操作对象

它使用 REDIS_ENCODING_ZIPLIST和REDIS_ENCODING_LINKEDLIST 这两种方式编码

一个列表最多可以包含232-1 个元素(4294967295, 每个列表超过40亿个元素)。

集合

REDIS_SET (集合) 是 SADD 、 SRANDMEMBER 等命令的操作对象

它使用 REDIS_ENCODING_INTSET 和 REDIS_ENCODING_HT 两种方式编码

Redis 中集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。

集合中最大的成员数为 232 - 1 (4294967295, 每个集合可存储40多亿个成员)

有序集

REDIS_ZSET (有序集)是ZADD 、ZCOUNT 等命令的操作对象

它使用 REDIS_ENCODING_ZIPLIST和REDIS_ENCODING_SKIPLIST 两种方式编码

不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。

有序集合的成员是唯一的,但分数(score)却可以重复。

集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。 集合中最大的成员数为 232 - 1 (4294967295, 每个集合可存储40多亿个成员)

Redis各种数据类型_以及它们的编码方式

过期时间

在数据库中,所有键的过期时间都被保存在 redisDb 结构的 expires 字典里:

typedef struct redisDb {

// ...

dict *expires;

// ...

} redisDb;

expires 字典的键是一个指向 dict 字典(键空间)里某个键的指针,而字典的值则是键所指 向的数据库键的到期时间,这个值以 long long 类型表示

过期时间设置

Redis 有四个命令可以设置键的生存时间(可以存活多久)和过期时间(什么时候到期):

EXPIRE 以秒为单位设置键的生存时间;

PEXPIRE 以毫秒为单位设置键的生存时间;

EXPIREAT 以秒为单位,设置键的过期 UNIX 时间戳;

PEXPIREAT 以毫秒为单位,设置键的过期 UNIX 时间戳。

虽然有那么多种不同单位和不同形式的设置方式,但是 expires 字典的值只保存“以毫秒为单位的过期 UNIX 时间戳” ,这就是说,通过进行转换,所有命令的效果最后都和 PEXPIREAT 命令的效果一样。

如果一个键是过期的,那它什么时候会被删除?

下边是参考答案

定时删除:在设置键的过期时间时,创建一个定时事件,当过期时间到达时,由事件处理 器自动执行键的删除操作。

惰性删除:放任键过期不管,但是在每次从 dict 字典中取出键值时,要检查键是否过 期,如果过期的话,就删除它,并返回空;如果没过期,就返回键值。

定期删除:每隔一段时间,对expires字典进行检查,删除里面的过期键

Redis 使用的过期键删除策略是惰性删除加上定期删除

应用场景

缓存

队列

需要精准设定过期时间的应用

比如你可以把上面说到的sorted set的score值设置成过期时间的时间戳,那么就可以简单地通过过期时间排序,定时清除过期数据了,不仅是清除Redis中的过期数据,你完全可以把Redis里这个过期时间当成是对数据库中数据的索引,用Redis来找出哪些数据需要过期删除,然后再精准地从数据库中删除相应的记录

排行榜应用,取TOP N操作

这个需求与上面需求的不同之处在于,前面操作以时间为权重,这个是以某个条件为权重,比如按顶的次数排序,这时候就需要我们的sorted set出马了,将你要排序的值设置成sorted set的score,将具体的数据设置成相应的value,每次只需要执行一条ZADD命令即可

统计页面访问次数

使用 incr 命令 定时使用 getset 命令 读取数据 并设置新的值 0

使用set 设置标签

例如假设我们的话题D 1000被加了三个标签tag 1,2,5和77,就可以设置下面两个集合:

$ redis-cli sadd topics:1000:tags 1

(integer) 1

$ redis-cli sadd topics:1000:tags 2

(integer) 1

$ redis-cli sadd topics:1000:tags 5

(integer) 1

$ redis-cli sadd topics:1000:tags 77

(integer) 1

$ redis-cli sadd tag:1:objects 1000

(integer) 1

$ redis-cli sadd tag:2:objects 1000

(integer) 1

$ redis-cli sadd tag:5:objects 1000

(integer) 1

$ redis-cli sadd tag:77:objects 1000

(integer) 1

要获取一个对象的所有标签:

$ redis-cli smembers topics:1000:tags

1. 5

2. 1

3. 77

4. 2

获得一份同时拥有标签1, 2,10和27的对象列表。

这可以用SINTER命令来做,他可以在不同集合之间取出交集

相关文章

  • 【Redis】Redis学习笔记(五)jedis(JedisCl

    redis系列文章目录 redis学习笔记(一)redis3.2.5集群安装与测试 redis学习笔记(二)Jed...

  • Redis学习笔记:事务

    Redis学习笔记:事务 原文链接:Redis学习笔记:事务 一、事务的描述 和MySQL一样,Redis中也有事...

  • Redis 参数

    Redis Redis 学习笔记 II 常见参数配置

  • 2018-11-12

    Redis学习笔记 Redis在在线测试 Redis官网 REmote DIctionary Server(Red...

  • Redis 初识

    初识 Redis 《 Redis 开发与运维》的学习笔记,希望大家多多指导。 什么是 Redis Redis 的全...

  • Redis—Redis入门安装及基础数据的知识

    Redis学习笔记所有文章:https://www.jianshu.com/nb/33547142 Redis安装...

  • 数据库Redis在Windows上的使用教程

    Redis学习笔记----Redis在windows上的安装配置和使用 Redis简介 redis是一个key-v...

  • Redis 学习笔记

    Redis 学习笔记 原文:硬核!16000 字 Redis 面试知识点总结,建议收藏! Redis 基础知识 R...

  • Redis 数据类型

    Redis Redis 学习笔记 II Redis是一个开源的使用ANSI C语言编写、遵守BSD协议、支持网络、...

  • Redis 安装

    Redis Redis 学习笔记 I Redis是一个开源的使用ANSI C语言编写、遵守BSD协议、支持网络、可...

网友评论

    本文标题:redis 学习笔记

    本文链接:https://www.haomeiwen.com/subject/lvmipxtx.html