Redis

Redis基础知识


 简单介绍一下Redis,以及为什么要用Redis做缓存?为什么要用缓存?

  Redis是一个使用C语言编写的非关系型数据库,与传统数据库不同的是,Redis的数据是存放在内存中的。由于数据存放在内存中,所以Redis对数据的读写非常的快。因此Redis被广泛应用于缓存方向,它每秒可以处理10万次的读写操作,是已知性能最快的Key-Value DB。另外Redis也经常被用来做分布式锁,甚至是消息队列。除此之外,Redis还提供了多种数据类型来支持不同的业务场景,并且它还支持事务持久化Lua脚本,多种集群方案。

使用Redis做缓存主要有以下两个方面的考虑:高性能、高并发。

  高性能:用户第一次访问数据库中的某些数据,这个过程会比较慢,因为是从硬盘上读取的,如果将数据放入缓存,下一次要读取这些数据的时候,直接从缓存中读取即可,操作内存的速度比硬盘是更快的,因此我们通常将不经常改变的数据放入缓存,用户要读取这些数据的时候,直接从缓存中读取,当数据库中的数据改变之后,同步改变缓存中的相应数据即可,这样能大大提高系统性能。

  高并发:在高并发场景下,往往会同时出现大量的请求打在数据库上,但是数据库能够承受的请求量是远远低于缓存的,因此可以考虑把数据库中的部分热点数据转移到缓存中去。

Redis和Memcached的区别和共同点

共同点:

  1. 都是基于内存的数据库,一般都用来做缓存使用;

  2. 都设置了过期策略;

  3. 两者的性能都非常高。

区别:

  1. 数据类型支持不同,与Memcached仅支持简单的key-value结构的数据记录不同,Redis支持的数据类型要丰富得多。最为常用的数据类型主要由五种:String、Hash、List、Set和Sorted Set。

  2. 内存管理机制不同,在Redis中,并不是所有的数据都一直存储在内存中的。这是和Memcached相比一个最大的区别。当物理内存用完时,Redis可以将一些很久没用到的value交换到磁盘。

  3. 数据持久化支持不同,Redis虽然是基于内存的存储系统,但是它本身是支持内存数据的持久化的,而且提供两种主要的持久化策略:RDB快照和AOF日志。而memcached是不支持数据持久化操作的。

  4. 集群的管理不同,Memcached本身并不支持分布式,因此只能在客户端通过像一致性哈希这样的分布式算法来实现Memcached的分布式存储。相较于Memcached只能采用客户端实现分布式存储,Redis更偏向于在服务器端构建分布式存储。

缓存数据的处理流程?

  


Redis数据结构以及应用场景

String 

1. 介绍: String数据结构是简单的key-value类型。

2. 常用指令:

set  | get | strlen | exists | decr | incr | setx | setnx 

3. 应用场景:一般用在需要计数的场景,比如用户的访问数量,热点文章的点赞和转发数据量等。

List

1. 介绍: list即链表,Redis的list的实现是一个双向链表。

2. 常用指令:

lpush | lpop | rpush | rpop | lrange | llen

消息队列: lpush 和 rpop 实现
栈: lpush 和 lpop 实现

3. 应用场景:一般用于发布和订阅(消息队列)和慢查询等。

Hash

1. 介绍: hash类似于hashmap,内部实现也差不多(数组+链表)。

2. 常用指令:

 hset | hmset | hget | hgetall | hmset | hexists | hkeys | hvals等

3. 应用场景:一般用于系统中对象数据的存储。

Set

1. 介绍:Set表示集合,类似于HashSet,存储不重复的无序数据。

2. 常用指令:

sadd | spop | smemembers | sismember | scard | sinterstore | sunin 等

3. 应用场景:一般用于需要存放不重复数据的场景或者多个数据源求交集和并集的场景(微博和B站的共同关注、共同好友、相同爱好推荐)。

Sorted Set

1. 介绍:Sorted Set表示有序集合,相比于Set,Sorted Set增加了一个权重参数score,能够按照score进行有序排列。

2. 常用指令:

zadd | zcard | zscore | zrange | zrevrange | zrem等

3. 应用场景:一般用于需要对数据根据某个权重进行排序的场景,比如直播系统中,包含直播间的在线用户列表,各种礼物排行榜等

Geo

1. 介绍:Geospatial地理位置

2. 常用指令:

geoadd | geodist | geohash | geopops | georadius | georadiusmember

3. 应用场景:一般用于推算两地间的距离,附近的人,朋友定位等

Hyperloglog

 1. 介绍:基数(不重复的元素),可以接受统计误差时才能使用,比set更节约内存空间。

2. 常用指令:

3. 应用场景:一般用于网页的UV(访问人数,一个人访问一个网站多次,但是还是算作一个人)

BitMap

1. 介绍:位存储。

2. 常用指令:

setbit | getbit | bitcount 

3. 应用场景:一般用于统计活跃、不活跃、登录、未登录、打卡、未打卡这种带两个状态的用户信息等

 

 


Redis单线程问题

为什么Redis选择单线程模型还那么快?

    1.  Redis完全基于内存,绝大部分请求为纯粹的内存操作;

    2.  数据结构简单,对数据操作也简单;

    3. 采用单线程更方便维护,避免了多线程带来的上下文切换和死锁等问题;

    4. Redis服务器使用非阻塞的IO多路复用机制,并发处理来自客服端的多个连接,极大的减少系统开销;

    5. Redis的性能瓶颈不在CPU,主要在内存和网络,所以多线程不能解决性能瓶颈问题。

Redis6.0之后为何又引入多线程?

    1. Redis 6.0 引入多线程主要是为了提高网络IO读写性能,多线程只是在网络数据的读写这类耗时的操作上使用,执行命令仍然是单线程顺序执行。

    2. 默认情况下,Redis6.0的多线程是被禁用的,只使用主线程。设置配置文件里面的: io-threads-do-reads为 yes 和 io-threads 为 4 来开启。


 IO多路复用是什么?

    Redis基于Reactor模式开发了自己的网络事件处理器,称之为文件事件处理器(File Event Hanlder)。文件事件处理器由Socket、IO多路复用程序、文件事件分派器(dispather),事件处理器(handler)四部分组成。

      IO多路复用程序会同时监听多个socket,当被监听的socket准备好执行accept、read、write、close等操作时,与这些操作相对应的文件事件就会产生。IO多路复用程序会把所有产生事件的socket压入一个队列中然后有序地每次仅一个socket的方式传送给文件事件分派器,文件事件分派器接收到socket之后会根据socket产生的事件类型调用对应的事件处理器进行处理。

文件事件处理器分为几种:

    连接应答处理器:用于处理客户端的连接请求;

    命令请求处理器:用于执行客户端传递过来的命令,比如常见的set、lpush等;

    命令回复处理器:用于返回客户端命令的执行结果,比如set、get等命令的结果;

事件种类:

    AE_READABLE:与两个事件处理器结合使用。当客户端连接服务器端时,服务器端会将连接应答处理器与socket的AE_READABLE事件关联起来;当客户端向服务端发送命令的时候,服务器端将命令请求处理器与AE_READABLE事件关联起来;

    AE_WRITABLE:当服务端有数据需要回传给客户端时,服务端将命令回复处理器与socket的AE_WRITABLE事件关联起来。


Redis缓存过期和内存淘汰

Redis缓存设置过期时间有啥用?

   一般情况下,我们保存的缓存数据都会设置一个过期时间,因为我们的内存是有限的,如果缓存中的数据一直保存的话,容易出现OutOfMemory错误。设置过期时间除了有助于缓解内存消耗,还适用于设置短信验证码和用户登录token等的有效时间。Redis除了字符串类型有自己独有设置过期时间的命令setex外,其他地方都需要依靠expire命令来设置过期时间。另外,persist命令可以移除一个键的过期时间。

Redis是如何判断缓存数据是否过期的?

   Redis通过一个过期字典来保存数据过期的时间。过期字典的键指向Redis数据库中的某个键(key),过期字典的值是一个long long类型的整数,这个整数保存了key所指向数据库键的过期时间。

过期数据的删除策略了解么?

  如果我们设置了一批key的过期时间为60s,那么60s之后,是怎样删除这批key的呢?常用的过期数据的删除策略主要有两个:

1. 惰性删除只有取出key的时候才对数据进行过期检查。这样对CPU友好,但是可能会造成太多过期key没有被删除。

2. 定期删除每隔一段时间抽取一批key执行删除过期key操作,并且,Redis底层会通过限制删除操作执行的时长和频率来减少删除操作对CPU的影响。

3. 定期删除对内存友好,惰性删除对CPU友好,所以Redis采用的是定期+惰性/懒汉式删除

Redis内存淘汰机制?

   仅仅通过设置key的过期时间,可能存在定期删除和惰性删除漏掉了很多过期key的情况。这样可能会导致大量key堆积在内存中,造成Out of Memeory,要解决这个问题需要内存淘汰机制。比如: MySQL里有2000W条数据,Redis里只能存20W条数据,如何保证Redis中的数据都是热点数据?

1. volatile-lru:从设置过期时间的数据集中挑选最近最少使用的数据淘汰。

2. volatile-ttl:   从设置过期时间的数据集中挑选将要过期的数据淘汰。

3. volatile-random: 从设置过期时间的数据集中任意选择数据淘汰。

4. volatile-lfu: 从设置过期时间的数据集中挑选最不经常使用的数据淘汰。

5. allkeys-lru: 从所有键数据集中挑选最近最少使用的数据淘汰。

6. allkeys-random: 从所有键数据集中任意选择数据淘汰。

7. allkeys-lfu: 从所有键数据集中挑选最不经常使用的数据淘汰。

8. no-eviction:   禁止淘汰数据,内存不足时,新写入数据直接报错。


Redis持久化

什么是Redis持久化?

   由于内存的有限容量和重启内存数据丢失等原因,我们需要将内存中的数据写入到硬盘中,以便之后重用数据,这就是持久化数据。Redis支持持久化,Memcached不支持持久化。

Redis持久化的实现方式?各自的优缺点是什么?

  Redis持久化的实现方式主要有两种: RDB快照(默认)、AOF日志

1. RDB快照:在指定的时间间隔内将内存中的数据集快照写入磁盘。实际操作过程是fork一个子进程,先将数据集写入临时文件,写入成功后,再替换之前的文件,用二进制压缩存储。,默认的文件名为dump.rdb。

 

 

 

触发方式:save、bgsave、自动触发三种方式。

优点:(1)适合大规模的数据恢复!(2)对数据的完整性要不高!
缺点:(1)需要一定的时间间隔进程操作!如果redis意外宕机了,这个最后一次修改数据就没有的了!(2)fork进程的时候,会占用一定的内存空间!! 

 

2. AOF日志:AOF持久化以日志的形式记录服务器所处理的每一个写、删除操作,查询操作不会记录,以文本的方式记录,可以打开文件看到详细的操作记录。,默认文件名为appendonly.aof。

触发方式:always、everysec、no

优点:(1)每一次修改都同步,文件的完整会更加好!(2)每秒同步一次,可能会丢失一秒的数据 (3)从不同步,效率最高的!
缺点: (1)相对于数据文件来说,aof远远大于 rdb,修复的速度也比 rdb慢!(2) Aof 运行效率也要比 rdb 慢,所以我们redis默认的配置就是rdb持久化!

 


 Redis主从复制

什么是主从复制?

   主从复制,是指将一台Redis服务器的数据,复制到其他的Redis服务器。前者称为主节点(master/leader),后者称为从节点(slave/follower);数据的复制是单向的,只能由主节点到从节点。Master以写为主,Slave 以读为主。默认情况下,每台Redis服务器都是主节点;且一个主节点可以有多个从节点(或没有从节点),但一个从节点只能有一个主节点。 

主从复制的作用?

1、数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式。
2、故障恢复:当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复;实际上是一种服务的冗余。
3、负载均衡:在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务(即写Redis数据时应用连接主节点,读Redis数据时应用连接从节点),分担服务器负载;尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高Redis服务器的并发量。
4、高可用(集群)基石:除了上述作用以外,主从复制还是哨兵和集群能够实施的基础,因此说主从复制是Redis高可用的基础。 

 

 

 一主二从

  主从复制,读写分离! 80% 的情况下都是在进行读操作!减缓服务器的压力!架构中经常使用! 一主二从!主机可以写,从机不能写只能读!主机中的所有信息和数据,都会自动被从机保存! Slave 启动成功连接到 master 后会发送一个sync同步命令Master 接到命令,启动后台的存盘进程,同时收集所有接收到的用于修改数据集命令,在后台进程执行完毕之后,master将传送整个数据文件到slave,并完成一次完全同步。
数据的同步方式:
  全量复制:用于初次复制或其它无法进行部分复制的情况,将主节点中的所有数据都发送给从节点。当数据量过大的时候,会造成很大的网络开销。(a) redis slave首启动或者重启后,连接到master时(b) redis slave进程没重启,但是掉线了,重连后不满足部分复制条件时,会触发全量复制。
  增量复制:只复制新增的数据,(a)redis slave进程没有重启,但是掉线了,重连了master (2)redis slave掉线期间,master保存在内存的offset可用,也就是master变化不大,被更改的指令都保存在内存时,会触发增量复制。
 
但是只要是重新连接master,一次完全同步(全量复制)将被自动执行! 
 哨兵模式
哨兵模式是一种特殊的模式,首先Redis提供了哨兵的命令,哨兵是一个独立的进程,作为进程,它会独立运行。其原理是哨兵通过发送命令,等待Redis服务器响应,从而监控运行的多个Redis实例。 如果故障了根据投票数自动将从库转换为主库。
优点:
  1、哨兵集群,基于主从复制模式,所有的主从配置优点,它全有
  2、 主从可以切换,故障可以转移,系统的可用性就会更好
  3、哨兵模式就是主从模式的升级,手动到自动,更加健壮!
缺点:
  1、Redis 不好啊在线扩容的,集群容量一旦到达上限,在线扩容就十分麻烦!
  2、实现哨兵模式的配置其实是很麻烦的,里面有很多选择! 

Redis缓存存在的问题

缓存穿透?

缓存击穿?

缓存雪崩?

 

posted @ 2021-06-20 13:19  sinlearn  阅读(119)  评论(0编辑  收藏  举报