Redis教程(介绍、数据类型、操作、特点、区别、容灾、一致性)

介绍

Redis 是一个开源的、支持网络、单进程单线程的、可基于内存、分布式、可选持久性的键值对(Key-Value)存储数据库.

数据类型

  • String: 字符串。 redis 的 string 可以包含任何数据。比如jpg图片或者序列化的对象。string 类型是 Redis最基本的数据类型,string 类型的值最大能存储 512MB。

  • Hash: 散列。和String的区别在于,Hash中可以存多个字段, hash 是一个 string 类型的 field(字段) 和 value(值) 的映射表,hash 特别适合用于存储对象。

  • List: 列表 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。

  • Set: 集合 Set是 string 类型的无序集合。集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。

  • Sorted Set: 有序集合(即zset) 区别在于可以通过给元素设置权重的方式改变集合的顺序。

高级数据类型:
HyperLogLog、Geo、Pub/Sub
Redis Module:
BloomFilter,RedisSearch,Redis-ML

Redis 与其他 key - value 缓存产品有以下三个特点:

  1. Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。
  • 与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。
  • Redis运行在内存中但是可以持久化到磁盘,所以在对不同数据集进行高速读写时需要权衡内存,因为数据量不能大于硬件内存。在内存数据库方面的另一个优点是,相比在磁盘上相同的复杂的数据结构,在内存中操作起来非常简单,这样Redis可以做很多内部复杂性很强的事情。同时,在磁盘格式方面他们是紧凑的以追加的方式产生的,因为他们并不需要进行随机访问。
  1. Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作
  2. Redis支持数据的备份,即master-slave模式的数据备份
  3. 原子性,Redis的所有操作都是原子性的,意思就是要么成功执行要么失败完全不执行。单个操作是原子性的。多个操作也支持事务,即原子性,通过MULTI和EXEC指令包起来。

redis操作

详见菜鸟教程 https://www.runoob.com/redis/redis-data-types.html

  • String: SET、GET
  • Hash:HSET、HGET、GETALL
    注:根据Redis 4.0.0,HMSET被视为已弃用。请在新代码中使用HSET。在之前,HSET仅能一次性加一个 而HMSET可以一次加多个
  • List:RPUSH、LPUSH BLPOP、BRPOP
  • SET SADD key member1 [member2]
  • ZSET: ZADD key score1 member1 [score2 member2]、ZRANGEBYSCORE

持久化

除了RDB(快照snapshots,即“拍照”将内存中的内容直接复制到硬盘的模式)持久化功能以外,Redis还提供了AOF(Append Only File)持久化功能。与RDB持久化通过保存数据库中的键值对来记录数据库状态不同,AOF持久化是通过保存Redis所执行的写命令来记录数据库状态的。

Redis是怎么持久化的?服务主从数据怎么交互的?

RDB做镜像全量持久化,AOF做增量持久化。因为RDB会耗费较长时间,不够实时,在停机的时候会导致大量丢失数据,所以需要AOF来配合使用。在redis实例重启时,会使用RDB持久化文件重新构建内存,再使用AOF重放近期的操作指令来实现完整恢复重启之前的状态。

这里很好理解,把RDB理解为一整个表全量的数据,AOF理解为每次操作的日志就好了,服务器重启的时候先把表的数据全部搞进去,但是他可能不完整,你再回放一下日志,数据不就完整了嘛。不过Redis本身的机制是 AOF持久化开启且存在AOF文件时,优先加载AOF文件;AOF关闭或者AOF文件不存在时,加载RDB文件;加载AOF/RDB文件城后,Redis启动成功;AOF/RDB文件存在错误时,Redis启动失败并打印错误信息

对方追问那如果突然机器掉电会怎样?

取决于AOF日志sync属性的配置,如果不要求性能,在每条写指令时都sync一下磁盘,就不会丢失数据。但是在高性能的要求下每次都sync是不现实的,一般都使用定时sync,比如1s1次,这个时候最多就会丢失1s的数据。

对方追问RDB的原理是什么?

你给出两个词汇就可以了,fork和cow。fork是指redis通过创建子进程来进行RDB操作,cow指的是copy on write,子进程创建后,父子进程共享数据段,父进程继续提供读写服务,写脏的页面数据会逐渐和子进程分离开来。

注:回答这个问题的时候,如果你还能说出AOF和RDB的优缺点,我觉得我是面试官在这个问题上我会给你点赞,两者其实区别还是很大的,而且涉及到Redis集群的数据同步问题等等。想了解的伙伴也可以留言,我会专门写一篇来介绍的。

Redis 管道技术

Redis 管道技术可以在服务端未响应时,客户端可以继续向服务端发送请求,并最终一次性读取所有服务端的响应。

Redis分区

  • 分区的优势

通过利用多台计算机内存的和值,允许我们构造更大的数据库。
通过多核和多台计算机,允许我们扩展计算能力;通过多台计算机和网络适配器,允许我们扩展网络带宽。

  • 分区的不足

redis的一些特性在分区方面表现的不是很好:
涉及多个key的操作通常是不被支持的。举例来说,当两个set映射到不同的redis实例上时,你就不能对这两个set执行交集操作。
涉及多个key的redis事务不能使用。
当使用分区时,数据处理较为复杂,比如你需要处理多个rdb/aof文件,并且从多个实例和主机备份持久化文件。
增加或删除容量也比较复杂。redis集群大多数支持在运行时增加、删除节点的透明数据平衡的能力,但是类似于客户端分区、代理等其他系统则不支持这项特性。然而,一种叫做presharding的技术对此是有帮助的。

  • 分区的类型 范围分区 哈希分区 一致性哈希分区

可见:https://www.jianshu.com/p/528ce5cd7e8f

数据的备份与容灾

缓存穿透 击穿 雪崩

缓存穿透:key对应的数据在数据源并不存在,每次针对此key的请求从缓存获取不到,请求都会到数据源,从而可能压垮数据源。比如用一个不存在的用户id获取用户信息,不论缓存还是数据库都没有,若黑客利用此漏洞进行攻击可能压垮数据库。简单的解决方案 对不存在的数据缓存 但是过期时间很短
缓存击穿(强调的是快):key对应的数据存在,但在redis中过期,此时若有大量并发请求过来,这些请求发现缓存过期一般都会从后端DB加载数据并回设到缓存,这个时候大并发的请求可能会瞬间把后端DB压垮。互斥锁·
缓存雪崩(范围广):当缓存服务器重启或者大量缓存集中在某一个时间段失效,这样在失效的时候,也会给后端系统(比如DB)带来很大压力。一个简单方案就时讲缓存失效时间分散开

底层结构

redis底层有6种数据结构,分别是简单动态字符串(SDS),链表,字典,跳跃表,整数集合,压缩列表。
每种数据类型都有着2种以上的数据结构实现,在不同状态下会进行数据结构的转换
在这里插入图片描述
sds是redis中对传统字符串的封装,在其上加入了长度等信息。用于redis中key等字符串类型数据的存储。
字典是一种可变的容器类型,键值对 如 dict = {‘a’: 1, ‘b’: 2, ‘b’: ‘3’}; dict采用了哈希表,最低能在 O(1)时间内完成搜索。同样的java的HashMap也是采用了哈希表实现,不同是dict在发生哈希冲突的时候采用了开放寻址法,而HashMap采用了链接法。
有些编程语言中称这种映射关系为字典, 因为它确实和生活中的字典比较相似. (比如Swift中Dictionary, Python中的dict)
有些编程语言中称这种映射关系为Map, 注意Map在这里不要翻译成地图, 而是翻译成映射. (比如Java中就有HashMap&TreeMap等)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

跳跃表 详见https://www.sohu.com/a/293236470_298038 一个有序的链表 跳跃着加多级索引
首先 数组查询快 可以二分查找 但是插入慢 链表查找慢 但是插入快 但是插入要等到查到到之后,那么怎么才能快一些呢?维护一组有序的集合,并且希望在查找、插入、删除等操作上尽可能快,那么跳跃表会是不错的选择。

整数集合(intset)是集合键的底层实现之一,当一个集合只包含整数值元素,并且这个集合的元素数量不多时,Redis就会使用整数集合作为集合键的底层实现。在这里插入图片描述
压缩列表 传统的列表每个的大小都是固定的 而我们为了节省 就压缩下 类似vchar https://www.cnblogs.com/hunternet/p/11306690.html

过期和内存淘汰策略 二者不同
https://www.cnblogs.com/mengchunchen/p/10039467.html

Redis注意事项

如果有大量的key需要设置同一时间过期,一般需要注意什么?

如果大量的key过期时间设置的过于集中,到过期的那个时间点,Redis可能会出现短暂的卡顿现象。严重的话会出现缓存雪崩,我们一般需要在时间上加一个随机值,使得过期时间分散一些。

电商首页经常会使用定时任务刷新缓存,可能大量的数据失效时间都十分集中,如果失效时间一样,又刚好在失效的时间点大量用户涌入,就有可能造成缓存雪崩

redis keys和scan

使用keys指令可以扫出指定模式的key列表。

对方接着追问:如果这个redis正在给线上的业务提供服务,那使用keys指令会有什么问题?
这个时候你要回答Redis关键的一个特性:Redis的单线程的。keys指令会导致线程阻塞一段时间,线上服务会停顿,直到指令执行完毕,服务才能恢复。这个时候可以使用scan指令,scan指令可以无阻塞的提取出指定模式的key列表,但是会有一定的重复概率,在客户端做一次去重就可以了,但是整体所花费的时间会比直接用keys指令长。

不过,增量式迭代命令也不是没有缺点的:举个例子, 使用 SMEMBERS 命令可以返回集合键当前包含的所有元素, 但是对于 SCAN 这类增量式迭代命令来说, 因为在对键进行增量式迭代的过程中, 键可能会被修改, 所以增量式迭代命令只能对被返回的元素提供有限的保证 。

Redis的同步机制了解么?

Redis可以使用主从同步,从从同步。第一次同步时,主节点做一次bgsave,并同时将后续修改操作记录到内存buffer,待完成后将RDB文件全量同步到复制节点,复制节点接受完成后将RDB镜像加载到内存。加载完成后,再通知主节点将期间修改的操作记录同步到复制节点进行重放就完成了同步过程。后续的增量数据通过AOF日志同步即可,有点类似数据库的binlog。

是否使用过Redis集群,集群的高可用怎么保证,集群的原理是什么?

Redis Sentinal 着眼于高可用,在master宕机时会自动将slave提升为master,继续提供服务。

Redis Cluster 着眼于扩展性,在单个redis内存不足时,使用Cluster进行分片存储。

没看完的

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值