redis学习笔记

本笔记参考书籍为:《redis实战》、《redis设计与实现》
一、初识redis
1.1简介
Redis是一个速度非常快的非关系数据库(non-relational database),它可以存储键(key)与 5 种不同类型的值(value)之间的映射(mapping),可以将存储在内存的键值对数据持久化到硬盘,可以使用复制特性来扩展读性能,还可以使用客户端分片来扩展写性能。
redis可以设置键的过期时间,过期键都保存在过期字典中,过期键的删除策略包括:
在这里插入图片描述
在这里插入图片描述
Redis 可以存储键与 5 种不同数据结构类型之间的映射,这 5 种数据结构类型分别为 STRING(字符串)、 LIST(列表)、 SET(集合)、 HASH(散列)和 ZSET(有序集合)。
redis的底层存储结构包括双端链表、字典、压缩链表、简单动态字符串、整数集合等。
redis分片操作:

	![在这里插入图片描述](https://img-blog.csdnimg.cn/20191213212804743.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM1Nzg0OTk2,size_16,color_FFFFFF,t_70)

1.2字符串
String的数据类型是由简单动态字符串(simple dynamic string SDS)实现的。
在这里插入图片描述
优点:
1、由于记录了长度,所以每次获取长度的时间复杂度都是O(n)。
2、通过定义未使用空间,可以做到空间预分配,优化了字符串增长操作。
在这里插入图片描述
在这里插入图片描述
1.3列表
在这里插入图片描述
列表的底层实现是用双向指针将多个压缩列表串联起来。也可以使用双端链表实现。

在这里插入图片描述

在这里插入图片描述
1.4集合
Redis 的集合和列表都可以存储多个字符串,它们之间的不同在于,列表可以存储多个相同的字符串,而
集合则通过使用散列表来保证自己存储的每个字符串都是各不相同的(这些散列表只有键,但没有与键相关联的值)。
存储方式:intset编码的集合对象底层实现是整数集合,所有元素都保存在整数集合中。hashtable编码的集合对象底层实现是字典,字典的每个键都是一个字符串对象,保存一个集合元素,不同的是字典的值都是NULL;可以参考java中的hashset结构。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
字典
在这里插入图片描述
压缩列表:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述在这里插入图片描述

1.5散列
实现方式:
ziplist编码的哈希对象底层实现是压缩列表,在ziplist编码的哈希对象中,key-value键值对是以紧密相连的方式放入压缩链表的,先把key放入表尾,再放入value;键值对总是向表尾添加。
hashtable编码的哈希对象底层实现是字典,哈希对象中的每个key-value对都使用一个字典键值对来保存。字典键值对即是,字典的键和值都是字符串对象,字典的键保存key-value的key,字典的值保存key-value的value。
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
1.6有序集合
实现方式:ziplist编码的有序集合对象底层实现是压缩列表,其结构与哈希对象类似,不同的是两个紧密相连的压缩列表节点,第一个保存元素的成员,第二个保存元素的分值,而且分值小的靠近表头,大的靠近表尾。
skiplist编码的有序集合对象底层实现是跳跃表和字典两种;每个跳跃表节点都保存一个集合元素,并按分值从小到大排列;节点的object属性保存了元素的成员,score属性保存分值;字典的每个键值对保存一个集合元素,字典的键保存元素的成员,字典的值保存分值。其实有序集合单独使用字典或跳跃表其中一种数据结构都可以实现,但是这里使用两种数据结构组合起来,原因是假如我们单独使用字典,虽然能以 O(1) 的时间复杂度查找成员的分值,但是因为字典是以无序的方式来保存集合元素,所以每次进行范围操作的时候都要进行排序;假如我们单独使用跳跃表来实现,虽然能执行范围操作,但是查找操作有 O(1)的复杂度变为了O(logN)。因此Redis使用了两种数据结构来共同实现有序集合。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
有序集合和散列一样,都用于存储键值对:有序集合的键被称为成员(member),每个成员都是各不
相同的;而有序集合的值则被称为分值(score),分值必须为浮点数。有序集合是 Redis 里面唯一一个既可以根据成员访问元素(这一点和散列一样),又可以根据分值以及分值的排列顺序来访问元素的结构。
在这里插入图片描述
二、使用redis构建web应用

三、redis命令
3.1字符串
字符串可以存储三种类型:字节串、整数、浮点数
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
3.2列表
3.3集合
3.4散列
在这里插入图片描述
3.5有序集合
在这里插入图片描述
3.6发布与订阅
发布与订阅(又称 pub/sub)的特点是订阅者(listener)负责订阅频道(channel),发送者(publisher)负责向频道发送二进制字符串消息(binary string message)。每当有消息被发送至给定频道时,频道的所有订阅者都会收到消息。
3.7其他
SORT命令,可以根据数字大小或者字典顺序排序
Redis 的基本事务(basic transaction)需要用到 MULTI 命令和 EXEC 命令,这种事务可以让一个客户端在不被其他客户端打断的情况下执行多个命令。和关系数据库那种可以在执行的过程中进行回滚(rollback)的事务不同,在 Redis 里面,被 MULTI 命令和 EXEC 命令包围的所有命令会一个接一个地执行,直到所有命令都执行完毕为止。当一个事务执行完毕之后, Redis 才会处理其他客户端的命令。
通过 Redis 的过期时间(expiration)特性来让一个键在给定的时限(timeout)之后自动被删除。
在这里插入图片描述
在这里插入图片描述
四、数据安全与性能保障
4.1redis持久化(一般来说是混合使用)
Redis 提供了两种不同的持久化方法来将数据存储到硬盘里面。一种方法叫快照(snapshotting)(RDB),它可以将存在于某一时刻的所有数据都写入硬盘里面。另一种方法叫只追加文件(append-only file,AOF),它会在执行写命令时,将被执行的写命令复制到硬盘里面。这两种持久化方法既可以同时使用,又可以单独使用,在某些情况下甚至可以两种方法都不使用,具体选择哪种持久化方法需要根据用户的数据以及应用来决定。
4.2RDB持久化
流程:
在这里插入图片描述

  1. Redis父进程首先判断:当前是否在执行save,或bgsave/bgrewriteaof(后面会详细介绍该命令)的子进程,如果在执行则bgsave命令直接返回。bgsave/bgrewriteaof 的子进程不能同时执行,主要是基于性能方面的考虑:两个并发的子进程同时执行大量的磁盘写操作,可能引起严重的性能问题。
  2. 父进程执行fork操作创建子进程,这个过程中父进程是阻塞的,Redis不能执行来自客户端的任何命令
  3. 父进程fork后,bgsave命令返回”Background saving started”信息并不再阻塞父进程,并可以响应其他命令
  4. 子进程创建RDB文件,根据父进程内存快照生成临时快照文件,完成后对原有文件进行原子替换
  5. 子进程发送信号给父进程表示完成,父进程更新统计信息
    RDB优点:
    (1)RDB会生成多个数据文件,每个数据文件都代表了某一个时刻中redis的数据。
    (2)RDB对redis对外提供读写服务的时候,影像非常小,因为redis 主进程只需要fork一个子进程出来,让子进程对磁盘io来进行rdb持久化
    (3).RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快。
    (4)RDB是一个紧凑的单一文件,很方便传送到另一个远端数据中心或者亚马逊的S3(可能加密),非常适用于灾难恢复。
    RDB缺点:
    (1)如果redis要故障时要尽可能少的丢失数据,RDB没有AOF好,例如1:00进行的快照,在1:10又要进行快照的时候宕机了,这个时候就会丢失10分钟的数据。
    (2)RDB每次fork出子进程来执行RDB快照生成文件时,如果文件特别大,可能会导致客户端提供服务暂停数毫秒或者几秒
    4.3AOF持久化
    简单来说, AOF 持久化会将被执行的写命令写到 AOF 文件的末尾,以此来记录数据发生的变化。因此, Redis 只要从头到尾重新执行一次 AOF 文件包含的所有写命令,就可以 恢 复 AOF 文 件 所 记 录 的 数 据 集 。
    实现方式:
    在这里插入图片描述
    数据恢复恢复:
    在这里插入图片描述
    创建一个不带网络连接的的伪客户端( fake client),因为 Redis 的命令只能在客户端上下文中执行,而载入 AOF 文件时所使用的的命令直接来源于 AOF 文件而不是网络连接,所以服务器使用了一个没有网络连接的伪客户端来执行 AOF 文件保存的写命令,伪客户端执行命令的效果和带网络连接的客户端执行命令的效果完全一样的。
    从 AOF 文件中分析并取出一条写命令。
    使用伪客户端执行被读出的写命令。
    一直执行步骤 2 和步骤3,直到 AOF 文件中的所有写命令都被处理完毕为止。
    **优点:**数据更完整,安全性更高,秒级数据丢失(取决fsync策略,如果是everysec,最多丢失1秒的数据)。**缺点:**对于相同的数据集,AOF文件的体积要大于RDB文件,数据恢复也会比较慢。
    4.4主从复制
    目的:读写分离、容灾恢复、数据备份
    第一阶段:与master建立连接
    第二阶段:向master发起同步请求(SYNC)
    第三阶段:接受master发来的RDB数据
    第四阶段:载入RDB文件
    部分复制:
    用于处理在主从复制中因网络闪断等原因造成的数据丢失场景,当从节点再次连上主节点后,如果条件允许,主节点会补发丢失数据给从节点,因为补发的数据远远小于全量数据,可以有效避免全量复制的过高开销,需要注意的是,如果网络中断时间过长,造成主节点没有能够完整的保存中断期间执行的写命令,则无法进行部分复制,仍使用全量复制
    4.5处理系统故障
    事务的(ACID)特性是由关系数据库管理系统(RDBMS,数据库系统)来实现的。数据库管理系统采用日志来保证事务的原子性、一致性和持久性。日志记录了事务对数据库所做的更新,如果某个事务在执行过程中发生错误,就可以根据日志,撤销事务对数据库已做的更新,使数据库退回到执行事务前的初始状态。数据库管理系统采用锁机制来实现事务的隔离性(事务的隔离级别)。当多个事务同时更新数据库中相同的数据时,只允许持有锁的事务能更新该数据,其他事务必须等待,直到前一个事务释放了锁,其他事务才有机会更新该数据。
    可以在系统故障发生之后,检查 AOF 文件和快照文件的状态,并在有需要的情况下对文件进行修复。它会扫描给定的 AOF 文件,寻找不正确或者不完整的命令,当发现第一个出错命令的时候,程序会删除出错的命令以及位于出错命令之后的所有命令,只保留那些位于出错命令之前的正确命令。
    在拥有一个主服务器和一个从服务器的情况下,更换主服务器的具体步骤:首先向机器B发送一个SAVE命令,让它创建一个新的快照文件,接着将这个快照文件发送给机器C,并在机器C上面启动Redis。最后,让机器B成为机器C的从服务器 。
    4.6redis事务
    在关系数据库中,用户首先向数据库服务器发送 BEGIN,然后执行各个相互一致(consistent)的写操作和读操作,最后,用户可以选择发送 COMMIT 来确认之前所做的修改,或者发送 ROLLBACK 来放弃那些修改。
    ******MULTI 命令的执行标记着事务的开始
    ******当客户端处于非事务状态下时, 所有发送给服务器端的命令都会立即被服务器执行。但是, 当客户端进入事务状态之后, 服务器在收到来自客户端的命令时, 不会立即执行命令, 而是将这些命令全部放进一个事务队列里, 然后返回 QUEUED。
    ******如果客户端正处于事务状态, 那么当 EXEC 命令执行时, 服务器根据客户端所保存的事务队列, 以先进先出(FIFO)的方式执行事务队列中的命令: 最先入队的命令最先执行, 而最后入队的命令最后执行。
    ******DISCARD 命令用于取消一个事务, 它清空客户端的整个事务队列, 然后将客户端从事务状态调整回非事务状态, 最后返回字符串 OK 给客户端, 说明事务已被取消。
    ******WATCH 命令用于在事务开始之前监视任意数量的键。
    ******Redis 在事务失败时不进行回滚,而是继续执行余下的命令。为什么:Redis 命令只会因为错误的语法而失败(并且这些问题不能在入队时发现),或是命令用在了错误类型的键上面:这也就是说,从实用性的角度来说,失败的命令是由编程错误造成的,而这些错误应该在开发的过程中被发现,而不应该出现在生产环境中。而且因为不需要对回滚进行支持,所以 Redis 的内部可以保持简单且快速。
    在这里插入图片描述
    事务开始(multi命令)---->事务入队---->事务执行
    在这里插入图片描述
    五、使用redis构建支持程序

    六、使用redis构建应用程序组件
    6.2分布式锁
    6.3计数信号量
    6.4任务队列
    6.5消息拉取
    七、基于搜索的应用程序
    搜索原理、索引
    八、构建简单的社交网络

    九、降低内存占用
    短结构:
    在列表、散列和有序集合的长度较短或者体积较小的时候, Redis 可以选择使用一种名为压缩列表(ziplist)的紧凑存储方式来存储这些结构。压缩列表是列表、散列和有序集合这 3 种不同类型的对象的一种非结构化(unstructured)表示:与 Redis 在通常情况下使用
    双链表表示列表、使用散列表表示散列、使用散列表加上跳跃表(skiplist)表示有序集合的做法不同,压缩列表会以序列化的方式存储数据,这些序列化数据每次被读取的时候都要进行解码,每次被写入的时候也要进行局部的重新编码,并且可能需要对内存里面的数据进行移动。
    分片结构:
    分片本质上就是基于某些简单的规则将数据划分为更小的部分,然后存储到不同的服务器上。
    **散列分片:**对散列进行分片首先需要选择一个方法来对数据进行划分。因为散列本身就存储着一些键,所以程序在对键进行划分的时候,可以把散列存储的键用作其中一个信息源,并使用散列函数为键计算出一个数字散列值。然后程序会根据需要存储的键的总数量以及每个分片需要存储的键数量,计算出所需的分片数量,并使用这个分片数量和键的散列值来决定应该把键存储到哪个分片里面。
    集合分片:
    打包存储二进制位和字节:
    十、扩展redis
    扩展读性能:
    使用只读从服务器提升系统处理读查询的性能,使得系统的读查询性能能够超过单台 Redis 服务器所能提供的读查询性能。对读查询的性能进行扩展,并将额外的服务器用作从服务器以提高系统处理读查询的性能。
    同时向多个从服务器发送快照的多个副本,可能会将主服务器可用的大部分带宽消耗殆尽。使主服务器的延迟变高,甚至导致主服务器已经建立了连接的从服务器断开。解决从服务器重同步(resync)问题的其中一个方法,就是减少主服务器需要传送给从服务器的数据数量,这可以通过构建一个如图所示的树状复制中间层来完成。
    在这里插入图片描述
    扩展写性能和内存容量:
    对数据进行分片,放到多台服务器上
    扩展复杂的查询:
    十一、redis的lua脚本编程

    redis分片:
    算法包括范围分片,哈希分片,一致性哈希算法
    客户端实现数据分片:即客户端自己计算数据的key应该在哪个机器上存储和查找,此方法的好处是降低了服务器集群的复杂度
    服务器实现数据分片:其理论是,客户端随意与集群中的任何节点通信,服务器端负责计算某个key在哪个机器上
    排序命令的实现:
    sort、desc、asc差不多都是这样排序的
    在这里插入图片描述
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值