redis常见问题总结

1.什么是Redis?

Redis是一个开源的使用ANSI C语言编写、遵守BSD协议、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API的非关系型数据库。

redis是一个以key-value存储的数据库结构型服务器,它支持的数据结构类型包括:字符串(String)、链表(lists)、哈希表(hash)、集合(set)、有序集合(Zset)等。为了保证读取的效率,redis把数据对象都存储在内存当中,它可以支持周期性的把更新的数据写入磁盘文件中。而且它还提供了交集和并集,以及一些不同方式排序的操作。


2.Redis的特点

1.redis数据读写速度非常快,因为它把数据都读取到内存当中操作,而且redis是用C语言编写的,是最“接近”操作系统的语言,所以执行速度相对较快。

2.redis虽然数据的读取都存在内存当中,但是最终它是支持数据持久化到磁盘当中。

3.redis提供了丰富的数据结构。

4.redis的所有操作都是原子性,支持事务,所谓的原子性就是对数据的更改要么全部执行,要么全部不执行。

5.redis支持主从复制,主机会自动将数据同步到从机,可以进行读写分离。


3.Redis是单进程单线程的为什么还能这么快?

1.完全基于内存,绝大部分请求是纯粹的内存操作,非常快速。

2.数据结构简单,对数据操作也简单,Redis中的数据结构是专门进行设计的。

3.采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗。

4.使用多路I/O复用模型,非阻塞IO。


4.什么是多路I/O复用

多路I/O复用模型是利用 select、poll、epoll 可以同时监察多个流的 I/O 事件的能力,在空闲的时候,会把当前线程阻塞掉,当有一个或多个流有 I/O 事件时,就从阻塞态中唤醒,于是程序就会轮询一遍所有的流(epoll 是只轮询那些真正发出了事件的流),并且只依次顺序的处理就绪的流,这种做法就避免了大量的无用操作。

这里“多路”指的是多个网络连接,“复用”指的是复用同一个线程。


5.Redis虚拟内存

和大多数NoSQL一样,Redis也是使用的KV的数据存储模型,为了提高读写效率,Redis也是将KV保存在内存中,但是这样做会带来一些问题。

如果内存足够大,那么把所有的数据都加载到内存中固然是最好的选择,那么查询操作都直接操作内存,自然是很快。但是实际情况中却更多的是只有部分数据才能加载到内存中,那么这个时候就提出来一个虚拟内存的概念。

Redis中的虚拟内存和Linux中的虚拟内存不是一回事,但是其思想是一致的,就是把暂时不常用的数据从内存交换到磁盘中,从而可以把宝贵的内存腾出来用于其他需要访问的数据,尤其是像Redis这样的内存数据库,内存的数量无意会成为一个瓶颈。虽然我们可以把数据分割到多个服务器上,但是虚拟内存依然是一个相当有效的解决办法。

使用虚拟内存还有另外一个原因,那就是在我们的数据库中,被访问的数据总是占全部数据的一小部分,而大部分的数据都是很少被访问的,就网站用户来说,活跃用户总是占据少部分。


6.Redis分布式锁

分布式锁的实现方式有三种,分别为数据库乐观锁、Redis的分布式锁和ZooKeeper的分布式锁。

Redis的分布式锁实现过程:

1.使用jedis的2.7.x及以上版本。

2.获取锁:

    命令:SET key value [NX|XX] [EX|PX] seconds

        NX – 只有键key不存在的时候才会设置key的值

        XX – 只有键key存在的时候才会设置key的值

        EX seconds – 设置键key的过期时间,单位时秒

        PX milliseconds – 设置键key的过期时间,单位时毫秒

3.释放锁

需要注意的地方:

①这个锁必须要设置一个过期时间。

②第一步获取锁的操作,把它实现成了两个Redis命令,SETNX+EXPIRE。虽然这两个命令和前面描述中的一个SET命令执行效果相同,但却不是原子的。如果客户端在执行完SETNX后崩溃了,那么就没有机会执行EXPIRE了,导致它一直持有这个锁。

③设置一个随机字符串randomVal是很有必要的,它保证了一个客户端释放的锁必须是自己持有的那个锁。

释放锁的操作必须使用Lua脚本来实现。释放锁其实包含三步操作:GET、判断和DEL,用Lua脚本来实现能保证这三步的原子性。


7.Redis主从复制读写分离

单机redis具有以下问题:(1) 如果机器出现故障,将导致redis不可用。(2) 单机的容量不能扩展。(3) 单机的OPS瓶颈不能很好解决

主从复制的作用:(1) 数据副本:多一份数据副本,保证redis高可用。(2) 扩展性能:如容量、QPS等.

主从复制的特点:(1) 一个master可以有多个slave 。(2) 一个slave只能有一个master 。(3) 数据流向是单向的,master到slave。

可能遇到的问题:(1) 复制数据的延迟:例如从节点发生阻塞,就会到值复制数据的延迟。(2) 读到过期的数据。(3) 从节点也有可能发生故障。


8.数据分片模型

Redis的分片技术是指将数据分散到多个Redis实例中的方法,分片之后,每个redis拥有一部分原数据集的子集。在数据量非常大时,这种技术能够将数据量分散到若干主机的redis实例上,进而减轻单台redis实例的压力。

分片的优点:

分片技术能够以更易扩展的方式使用多台计算机的存储能力(这里主要指内存的存储能力)和计算能力:

  1. 从存储能力的角度,分片技术通过使用多台计算机的内存来承担更大量的数据,如果没有分片技术,那么redis的存储能力将受限于单台主机的内存大小。
  2. 从计算能力的角度,分片技术通过将计算任务分散到多核或者多台主机中,能够充分利用多核、多台主机的计算能力。

分片的缺陷:

  1. 通常无法支持涉及多键的操作;在redis中有很多一次操作多个key的操作,例如求集合交集的SINTER操作,该操作将涉及到多个键,而这多个键有可能被分片到不同的redis实例中,此时就无法执行这种操作。
  2. Redis的事务操作中涉及多个键时也不能用。
  3. 分片将导致数据处理更加复杂;例如在分片过程中,随着redis实例的增加,数据备份等操作都将会变得更加复杂。
  4. Redis目前不支持动态分片操作,扩容和缩容操作都会比较复杂,尤其分片操作部署在客户端时,需要重新配置和启动客户端。在使用过程中缩容用的不多,扩容可以采用后面介绍的预分片策略来缓解此问题。

分片部署方式一般分为以下三种:

  1. 在客户端做分片:这种方式在客户端确定要连接的redis实例,然后直接访问相应的redis实例。
  2. 在代理中做分片:这种方式中,客户端并不直接访问redis实例,它也不知道自己要访问的具体是哪个redis实例,而是由代理转发请求和结果。其工作过程为:客户端先将请求发送给代理,代理通过分片算法确定要访问的是哪个redis实例,然后将请求发送给相应的redis实例,redis实例将结果返回给代理,代理最后将结果返回给客户端。

在redis服务器端做分片:这种方式被称为“查询路由”,在这种方式中客户端随机选择一个redis实例发送请求,如果所请求的内容不再当前redis实例中它会负责将请求转交给正确的redis实例。或者,redis实例不会转发请求,而是将正确redis的信息发给客户端,由客户端再去向正确的redis实例发送请求。


9.Redis的内存回收策略

Redis内存回收机制主要体现在以下两个方面:(1) 删除到达时间的键对象。(2) 内存使用达到maxmemory上限时触发内存溢出控制策略。

1.redis采用惰性删除和定时任务删除机制实现过期键的内存回收

惰性删除用于当客户端读取带有超时属性的键时,如果已经超过键设置的过期时间,会执行删除操作并返回空,这种策略是出于节省CPU成本考虑,不需要单独维护TTL链表来处理过期键的删除。但是单独用这种方式存在内存泄露的问题,当过期键一直没有访问将无法得到及时删除,从而导致内存不能及时释放。

定时任务删除:Redis内部维护一个定时任务,默认每秒运行10次(通过配置hz控制)。定时任务中删除过期键逻辑采用了自适应算法,根据键的过期比例,使用快慢两种速率模式回收键。

2.内存溢出控制策略

  • noeviction:默认策略,当内存不足以容纳新写入数据时,新写入操作会报错。
  • allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的Key。(推荐)
  • allkeys-random:当内存不足以容纳新写入数据时,在键空间中,随机移除某个Key。
  • volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的Key。
  • volatile-random:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个Key。
  • volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的Key优先移除。

10.Redis相比Memcached有哪些优势

(1)memcached所有的值均是简单的字符串,redis作为其替代者,支持更为丰富的数据类型。

(2)redis的速度比memcached快很多。

(3)redis可以持久化其数据。

(4)Redis支持数据的备份,即master-slave模式的数据备份。

(5)value大小:redis最大可以达到1GB,而memcached只有1MB。

(6)使用底层模型不同,它们之间底层实现方式 以及与客户端之间通信的应用协议不一样。


11.Redis常见性能问题和解决方案

(1)Master最好不要做任何持久化工作,如RDB内存快照和AOF日志文件

(2)如果数据比较重要,某个Slave开启AOF备份数据,策略设置为每秒同步一次

(3)为了主从复制的速度和连接的稳定性,Master和Slave最好在同一个局域网内

(4)尽量避免在压力很大的主库上增加从库

(5)主从复制不要用图状结构,用单向链表结构更为稳定,即:Master <- Slave1 <- Slave2 <- Slave3...这样的结构方便解决单点故障问题,实现Slave对Master的替换。如果Master挂了,可以立刻启用Slave1做Master,其他不变。


12.Redis持久化机制

Redis支持RDB和AOF两种持久化机制,持久化功能有效地避免因进程退出造成的数据丢失问题,当下次重启时利用之前持久化的文件即可实现数据恢复。

1.RDB持久化

RDB持久化是把当前进程数据生成快照保存到硬盘的过程,触发RDB持久化过程分为手动触发和自动触发。

优点:①RDB是一个紧凑压缩的二进制文件,代表Redis在某个时间点上的数据快照。非常适用于备份,全量复制等场景。②Redis加载RDB恢复数据远远快于AOF的方式。

缺点:①RDB方式数据没办法做到实时持久化/秒级持久化。因为bgsave每次运行都要执行fork操作创建子进程,属于重量级操作,频繁执行成本过高。②RDB文件使用特定二进制格式保存,Redis版本演进过程中有多个格式 的RDB版本,存在老版本Redis服务无法兼容新版RDB格式的问题。

2.AOF持久化

AOF(append only file)持久化:以独立日志的方式记录每次写命令,重启时再重新执行AOF文件中的命令达到恢复数据的目的。

优点:如果不考虑性能,AOF可以最大限度保证数据完整性,可以设置每发生一次写操作就调用一次fsync函数;更加灵活,可以使用不同的fsync策略,完全不使用fsync,每秒使用fsync(默认),以及每次查询时使用fsync。

缺点:与RDB方式相比,相同数据集大小AOF占用空间更大;若调用fsync的频率过快,性能会变差。


13.什么是缓存穿透、缓存击穿和缓存雪崩以及如何处理

1.缓存穿透:

缓存穿透是指缓存和数据库中都没有的数据,而用户不断发起请求,如发起为id为“-1”的数据或id为特别大不存在的数据。这时的用户很可能是攻击者,攻击会导致数据库压力过大。

解决办法:

(1)接口层增加校验,如用户鉴权校验,id做基础校验,id<=0的直接拦截;

(2)从缓存取不到的数据,在数据库中也没有取到,这时也可以将key-value对写为key-null,缓存有效时间可以设置短点,如30秒(设置太长会导致正常情况也没法使用)。这样可以防止攻击用户反复用同一个id暴力攻击。

2.缓存击穿:

缓存击穿是指缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力。

解决办法:

(1)设置热点数据永远不过期。

(2)加互斥锁。

3.缓存雪崩

缓存雪崩是指缓存中数据大批量到过期时间,而查询数据量巨大,引起数据库压力过大甚至down机。和缓存击穿不同的是,缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了,很多数据都查不到从而查数据库。

解决办法:

(1)缓存数据的过期时间设置随机,防止同一时间大量数据过期现象发生。

(2)如果缓存数据库是分布式部署,将热点数据均匀分布在不同的缓存数据库中。

(3)设置热点数据永远不过期。


14.Redis最适合的场景

1.redis由于数据的读取和操作都在内存当中操作,读写的效率较高,所以经常被用来做数据的缓存。把一些需要频繁访问的数据,而且在短时间之内不会发生变化的,放入redis中进行操作。从而提高用户的请求速度和降低网站的负载,降低数据库的读写次数,就把这些数据放到缓存中。

2.一些常用的实时计算的功能。需要实时变化和展示的功能,就可以把相关数据放在redis中进行操作。大大提高效率。

3.消息队列,经常用来构建类似实时聊天系统的功能,大大提高应用的可用性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值