redis知识整理

时间:2021-09-05
本文章向大家介绍redis知识整理,主要包括redis知识整理使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

 1、Redis是什么?

  简单来说 redis 就是一个数据库,不过与传统数据库不同的是 redis 的数据是存在内存中的,所以存写速度非常快,因此 redis 被广泛应用于缓存方向。另外,redis 也经常用来做分布式锁。redis 提供了多种数据类型来支持不同的业务场景。除此之外,redis 支持事务 、持久化、LUA脚本、LRU驱动事件、多种集群方案。

2、Redis 有哪些应用场景

  1、热点数据的缓存:由于redis访问速度块、支持的数据类型比较丰富,所以redis很适合用来存储热点数据。

  2、分布式锁:多并发情况下,使用 setnx和expire(原子性操作下)加锁,以及当线程执行到一定时间还未结束使用守护线程,用来给快要过期的锁“续航”。

  3、做计数器:redis由于incrby命令可以实现原子性的递增,所以可以运用于高并发的秒杀活动、分布式序列号的生成、具体业务还体现在比如限制一个手机号发多少条短信、一个接口一分钟限制多少请求、一个接口一天限制调用多少次等等。

  等。。

3、Redis 支持哪些数据类型?

  String(字符串)、List(列表)、Set(集合)、Zset(Sorted Set:有序集合)、以及Hash(哈希)。

4、Redis 持久化有什么用?

  用于快速恢复数据。Redis为了内部数据的安全考虑,会把本身的数据以文件的形式保存在硬盘中一份,在重启之后会自动把硬盘的数据恢复到内存(redis)里面。

5、Redis 持久化之RDB和AOF

  1、Redis 默认开启RDB持久化方式,在指定的时间间隔内,执行指定次数的写操作,则将内存中的数据写入到磁盘中。

  2、RDB 持久化适合大规模的数据恢复但它的数据一致性和完整性较差(镜像全量持久化)。

  3、Redis 需要手动开启AOF持久化方式,默认是每秒将写操作日志追加到AOF文件中(增量持久化)。

  4、AOF 的数据完整性比RDB高,但记录内容多了,会影响数据恢复的效率。

  5、Redis 针对 AOF文件大的问题,提供重写的瘦身机制。

  6、若只打算用Redis 做缓存,可以关闭持久化。

  7、若打算使用Redis 的持久化。建议RDB和AOF都开启。其实RDB更适合做数据的备份,留一后手。AOF出问题了,还有RDB。

  AOF的重写机制:

  AOF的工作原理是将写操作追加到文件中,文件的冗余内容会越来越多。所以聪明的 Redis 新增了重写机制。当AOF文件的大小超过所设定的阈值时,Redis就会对AOF文件的内容压缩。

  重写的原理:Redis 会fork出一条新进程,读取内存中的数据,并重新写到一个临时文件中,最后替换旧的aof文件。

6、什么是Redis跳跃表?

  跳跃表:将有序链表改造为可以支持链表式“二分查找”算法,可以快速的进行插入、删除、查找。

  跳跃表查找节点的过程(以插入元素为例,删除、查找的过程是一样的)
  1、从head开始,根据forward指针(箭头)向前查找,如果前一个元素大于待查找的元素或者遇到tail指针(红色线情况),下移层次继续查找(红色线头节点为起始点);如果下一个元素不大于待查找的元素,forward向前推进一个节点,继续比较。
  2、重复1步骤,直到遇到的前一个节点的值大于待查找的值
  最终总是能找到比待查找节点的值大的前一个位置,在这个位置插入元素。
  跳跃表插入数据时,层级为投硬币的方式随机生成level高度,然后找到前置节点进行插入(比如22,1层)。
  

 7、Redis 内存满了怎么办?

  1、通过配置文件配置

  通过在Redis安装目录下面的redis.conf配置文件中添加以下配置设置内存大小

  maxmemory 100mb

   2、内存淘汰策略  

  内存淘汰策略相当于清除掉那些占用内存并且使用不太频繁的数据,淘汰掉这些不活跃数据来清理内存。

    a)LRU 剔除最近最少使用

    volatile-lru:从全数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰

    allkeys-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰

    b)LFU剔除最近使用频率最低

    volatile-lfu:从全数据集(server.db[i].dict)中挑选最近使用频率最低的数据淘汰

    allkeys-lfu:从已设置过期时间的数据集(server.db[i].expires)中挑选最近使用频率最低的数据淘汰

       c)Random随机剔除

    volatile-lfu:从全数据集(server.db[i].dict)中随机数据淘汰

    allkeys-lfu:从已设置过期时间的数据集(server.db[i].expires)中随机数据淘汰

    d)其他

    noeviction:默认策略,不驱逐,不会继续服务写请求 (DEL 请求可以继续服务),读请求可以继续进行。这样可以保证不会丢失数据,但是会让线上的业务不能持续进行。

    volatile-ttl:在设置了过期时间的键空间中,具有更早过期时间的key优先移除。

8、Redis6.0之后支持多线程,开启多线程后,是否会存在线程并发安全问题?

  不会,Redis 的多线程部分只是用来处理网络数据的读写和协议解析,执行命令仍然是单线程顺序执行。

9、Redis使用的I/O多路复用epoll

  I/O多路复用:单个线程,通过记录跟踪每个I/O流(sock)的状态,来同时管理多个I/O流 。select, poll, epoll 都是I/O多路复用的具体的实现。

  三者区别:

  1、底层数据结构

  select:数组,poll:链表,epoll:红黑树。

  2、支持一个进程所能打开的最大连接数  

  select 单个进程所能打开的最大连接数有1024(x86)或2048(x64)。poll无上限。epoll 虽然连接数有上限,但是很大,1G内存的机器上可以打开10万左右的连接,2G内存的机器可以打开20万左右的连接。

  3、FD剧增后带来的IO效率问题

  Epoll最大的优点就在于它只管你“活跃”的连接,而跟连接总数无关,因此在实际的网络环境中,Epoll的效率就会远远高于select和poll。

  4、消息传递方式

  select/poll 内核需要将消息传递到用户空间,都需要内核拷贝动作。epoll通过内核和用户空间共享一块内存来实现的。

10、假如Redis里面有1亿个key,其中有10w个key是以某个固定的已知的前缀开头的,生产环境下,如何将它们全部找出来?

  redis的命令是单线程的。keys指令会导致线程阻塞一段时间,线上服务会停顿,直到指令执行完毕,服务才能恢复。这个时候可以使用scan指令,scan指令可以无阻塞的提取出指定模式的key列表,但是会有一定的重复概率,在客户端做一次去重就可以了,但是整体所花费的时间会比直接用keys指令长。

11、什么是缓存穿透,缓存雪崩,缓存击穿?如何解决或预防? 

  我一个QPS不到10的项目,天天问我缓存穿透、缓存击穿、缓存雪崩,我是真滴难T T。

  a)缓存穿透:

  访问一个缓存和数据库都不存在的 key,此时会直接打到数据库上,并且查不到数据,没法写缓存,所以下一次同样会打到数据库上。

  此时,缓存起不到作用,请求每次都会走到数据库,流量大时数据库可能会被打挂。此时缓存就好像被“穿透”了一样,起不到任何作用。

   解决预防方案:

  1、接口校验。在正常业务流程中可能会存在少量访问不存在 key 的情况,但是一般不会出现大量的情况,所以这种场景最大的可能性是遭受了非法攻击。可以在最外层先做一层校验:用户鉴权、数据合法性校验等,例如商品查询中,商品的ID是正整数,则可以直接对非正整数直接过滤等等。

  2、缓存空值。当访问缓存和DB都没有查询到值时,可以将空值写进缓存,但是设置较短的过期时间,该时间需要根据产品业务特性来设置。

  3、布隆过滤器

  布隆过滤器应用场景:

  • 在爬虫时,对爬虫网址进行过滤,已经存在布隆中的网址,不在爬取。
  • 垃圾邮件过滤,对每个发送邮件的地址进行判断是否在布隆的黑名单中,若是在就判断为垃圾邮件。
  • 缓存穿透。

  布隆过滤器特性:

  布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都远远超过一般的算法,缺点是有一定的误识别率和删除困难。

  原理:在一个足够大的足够大的 bitmap中,插入时与多个不同的hash函数生成多个哈希值,将对应位置置1。查找时如果发现所有hash函数对应位都是1说明存在,只要有一个为0则认为这个元素不存在。(hash冲突会导致一定的误识别率)

  b)缓存雪崩:

  缓存雪崩:指在某一个时间段,缓存集中过期失效。Redis宕机。

  解决预防方案:

  1、优化缓存过期时间:设计缓存时,让过期时间尽量均匀,避免大量的 key 在同一时刻同时失效,造成缓存雪崩。

  2、集群:可以把缓存层设计成高可用的,即使个别节点、个别机器、甚至是机房宕掉,依然可以提供服务。利用sentinel或cluster实现。

  3、构建多级缓存架构:nginx缓存 + redis缓存 +其他缓存(ehcache等)。

  c)缓存击穿:

  指一个热点key被大并发量请求,热点key突然失效时,大批量请求涌向数据库,导致数据库的压力瞬间过大

  解决预防方案:

  1、预先设置热门数据

  在Redis高峰访问之前,把一些热门数据提前存入Redis中,并且加大这些热门数据key的时长。

  2、互斥锁用分布式锁控制访问的线程,其他线程等待,等到抢到锁的线程从数据库中加载数据完毕。

  3、本地缓存:把缓存数据取出时直接加载到本地缓存(Ehcache、Guava Cache),这样访问热key时就可以直接访问呢自己缓存了。

12、redis集群三种方式

  1、主从模式:可以一主多从,主从数据同步保证数据完整性,且可以实现写主、读从,性能有所提升,但主节点故障后写受影响,没有故障选举功能,且无监控各主从运行状态功能。

  2、哨兵模式:哨兵(sentinel)监控各节点运行状态,主节点发生故障后长(经历主观下线和客观下线),可以通过再次选举产生主节点,实现故障恢复,但若从节点挂了不能实现从节点的故障转移;

  选举机制:

  如果主节点被判定为客观下线之后,就要选取一个哨兵节点来完成后面的故障转移工作,选举出一个leader的流程如下:

  a)每个在线的哨兵节点都可以成为领导者,当它确认(比如哨兵3)主节点下线时,会向其它哨兵发is-master-down-by-addr命令,征求判断并要求将自己设置为领导者,由领导者处理故障转移;

  b)当其它哨兵收到此命令时,可以同意或者拒绝它成为领导者;

  c)如果哨兵3发现自己在选举的票数大于等于num(sentinels)/2+1以及quorum数时,将成为领导者,如果没有超过,继续选举

  3、cluster集群:Redis Cluster 是一种服务器 Sharding 技术(分片和路由都是在服务端实现),采用多主多从,每一个分区都是由一个 Redis 主机和多个从机组成,片区和片区之间是相互平行的。Redis Cluster 集群采用了 P2P 的模式,完全去中心化。

  工作原理:

  • 集群完全去中心化,采用多主多从;所有的 redis 节点彼此互联(PING-PONG 机制),内部使用二进制协议优化传输速度和带宽。
  • 客户端与 Redis 节点直连,不需要中间代理层。客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可。
  • 每一个 master 节点负责维护一部分槽,以及槽所映射的键值数据;集群中每个节点都有全量的槽信息,通过槽每个 node 都知道具体数据存储到哪个 node 上。根据公式HASH_SLOT=CRC16(key) mod 16384,计算出映射到哪个分片上,然后Redis会去相应的节点进行存取操作。
  • 为了保证高可用,redis-cluster集群引入了主从模式,一个主节点对应一个或者多个从节点,当主节点宕机的时候,就会启用从节点。

13、如何保证 Redis 缓存与数据库双写一致性

  1、加分布式读写锁(适合读多写少场景):通过加锁保证并发读写,写写的时候按顺序排好队,读读不影响。(加读写锁可能会导致系统变得沉重,系统变慢)

  2、为缓存设置超时时间(适合允许一段时间DB和缓存不一致的场景):每隔一段时间自动刷新缓存。

  3、使用Canal解决缓存一致性问题: Mysql 数据库更新操作后再 binlog 日志中我们都能够找到相应的操作,那么我们可以订阅 Mysql 数据库的 binlog 日志对缓存进行操作。(用Canal需要额外增加Canal中间件,加重系统复杂度)。

  

原文地址:https://www.cnblogs.com/luoyanyu/p/15226578.html