当前位置:   article > 正文

redis常见问题及解决方案_redis 常见问题

redis 常见问题

欢迎大家留言指正


前言

redis常见问题汇总

一、redis常见问题

1、Redis如何实现延时队列?

使用sortedset,使用时间戳做score, 消息内容作为key,调用zadd来生产消息,消费者使用zrangbyscore获取n秒之前的数据做轮询处理

2、redis缓存击穿是什么?如何解决?

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

解决方案

1.设置热点数据永远不过期:使用mutex,缓存失效的时候(判断拿出来的值为空),不是立即去loaddb,而是先使用缓存工具的某些带成功的返回值操作(例如reids的SETNX或者memcache的add)去set一个mutexkey,当返回成功时,在进行load db操作并回设缓存,否则就重试整个get缓存方法。

3、redis缓存穿透是什么?如何解决?

缓存穿透是指缓存和数据库中都没有的数据,导致所有的请求都落到数据库上,造成数据库短时间内承受大量请求而崩掉。

解决方案

  1. 接口层增加校验,如用户鉴权校验,id做基础校验,id<=0的直接拦截;
  2. 从缓存取不到的数据,在数据库中也没有取到,这时也可以将key-value对写为key-null,缓存有效时间可以设置短点,如30秒(设置太长会导致正常情况也没法使用)。这样可以防止攻击用户反复用同一个id暴力攻击。
  3. 【推荐】采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的 bitmap 中,一个一定不存在的数据会被这个 bitmap 拦截掉,从而避免了对底层存储系统的查询压力。

4、redis缓存雪崩是什么?如何解决?

缓存雪崩是指缓存同一时间大面积的失效,所以,后面的请求都会落到数据库上,造成数据库短时间内承受大量请求而崩掉。

解决方案

1.缓存数据的过期时间进行错开,防止同一时间大量数据过期现象发生。
2.像缓存穿透一样加锁排列。
3.建立备份缓存,设置A的过期时间,不设置B的过期时间,当缓存A失效的时候,读取缓存B,并且更新A的缓存和B的缓存。

5、redis的list队列先进先出如何解决插队问题?

通常使用一个list来实现队列操作,这样有一个小限制,所以的任务统一都是先进先出,如果想优先处理某个任务就不太好处理了,这就需要让队列有优先级的概念,我们就可以优先处理高级别的任务,实现方式有以下几种方式:

  1. 单一列表实现:队列正常的操作是 左进右出(lpush,rpop)为了先处理高优先级任务,在遇到高级别任务时,可以直接插队,直接放入队列头部(rpush),这样,从队列头部(右侧)获取任务时,取到的就是高优先级的任务(rpop)。
  2. 使用两个队列,一个普通队列,一个高级队列,针对任务的级别放入不同的队列,获取任务时也很简单,redis的BRPOP命令可以按顺序从多个队列中取值,BRPOP会按照给出的 key 顺序查看,并在找到的第一个非空 list 的尾部弹出一个元素,redis> BRPOP list1 list2 0list1 做为高优先级任务队列 list2 做为普通任务队列这样就实现了先处理高优先级任务,当没有高优先级任务时,就去获取普通任务。

解决方案

方式1最简单,但实际应用比较局限,
方式2是推荐用法,实际应用最为合适

6、使用redis你lpop一条数据后, 插入数据库失败怎么办?

一般使用list结构作为队列,rpush生产消息,lpop消费消息。当lpop没有消息的时候,要适当sleep一会再重试。
缺点:
在消费者下线的情况下,生产的消息会丢失

解决方案

使用专业的消息队列如rabbitmq等。

7、redis如何优化?

  1. 建立redis连接池。
  2. 建立redis集群和一主多从。
  3. 设置key有效期。
  4. 设置bit级别的存储,如GETBIT 和 SETBIT等。
  5. 想要一次添加多条数据的时候可以使用管道 。
  6. 根据业务需要选择合适的数据类型,并为不同的应用场景设置相应的紧凑存储参数。
  7. 当业务场景不需要数据持久化时,关闭所有的持久化方式可以获得最佳的性能以及最大的内存使用量。
  8. 如果需要使用持久化,根据是否可以容忍重启丢失部分数据在快照方式与语句追加方式之间选择其一,不要使用虚拟内存以及diskstore方式。
  9. 不要让你的Redis所在机器物理内存使用超过实际内存总量的3/5。

8、Redis的内存用完了会发生什么?

如果达到设置的上限,Redis的写命令会返回错误信息(但是读命令还可以正常返回。)

解决方案

可以配置内存淘汰机制,当Redis达到内存上限时会冲刷掉旧的内容。

12.redis如何做内存优化?

尽可能使用散列表,散列表使用的内存非常少,所以尽可能的将数据抽象到三列表里。

9、Redis的内存淘汰策略有哪些?

Redis的内存淘汰策略是指在Redis的用于缓存的内存不足时,怎么处理需要新写入且需要申请额外空间的数据。

  1. 全局的键空间选择性移除:
    1.1 noeviction:当内存不足以容纳新写入数据时,新写入操作会报错。
    1.2 allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的key。(这个是最常用的)
    1.3 allkeys-random:当内存不足以容纳新写入数据时,在键空间中,随机移除某个key。
  2. 设置过期时间的键空间选择性移除:
    2.1 volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的key。
    2.2 volatile-random:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个key。
    2.3 volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的key优先移除。

10.如何查找一亿数据中的10W个key?

使用keys扫描出所有指定模式的key列表,如果这个redis正在为线上提供服务,这会造成阻塞卡顿,因为redis是单线程的,keys指令会导致线程阻塞一段时间,线上服务停顿,直到指令执行完毕,服务才能恢复,scan命令可以无阻塞提取指定模式的key列表,但可能给会有重复的概率,在客户端去重一次就好,整个执行时间比keys长。(利用scan系列命令(SCAN、SSCAN、HCAN、ZCAN)完成数据迭代

11、对比下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。

12.redis集群什么情况下会导致集群不可用?

A、B、C三个节点集群,当B节点失败,那么整个集群会因为缺失B节点范围的槽而不可用。

13.redis回收进程机制如何工作?

一个客户端运行了新的命令,添加了新的数据,redis检查内存的使用清理,如果大于maxmemory的限制,则根据设定好的策略进行回收,所以就是内存不断的达到限制边界,不断的会受到边界以内,如果一个内存导致内存被大量占用,不用多久,内存很快就会被超越。

14.redis如何保证都是热数据?

redis内存数据集大小升到一定的大小后,就会实行数据淘汰策略。

15.redis连接connect和pconnect区别?

connect结束后连接断开,pconnect结束后连接不断开,保持在php-fpm进程中。

16.redis有哪些优缺点?

  1. 优点:
    1.1 读写性能优异。
    1.2 支持数据持久化,支持AOF和RDB两种持久化方式。
    1.3 支持事务,Redis的所有操作都是原子性的,同时Redis还支持对几个操作合并后的原子性执行。
    数据结构丰富,除了支持string类型的value外还支持hash、set、zset、list等数据结构。
    1.4 支持主从复制,主机会自动将数据同步到从机,可以进行读写分离。
  2. 缺点:
    2.1 数据库容量受到物理内存的限制,不能用作海量数据的高性能读写,因此Redis适合的场景主要局限在较小数据量的高性能操作和运算上。
    2.2 redis 不具备自动容错和恢复功能,主机从机的宕机都会导致前端部分读写请求失败,需要等待机器重启或者手动切换前端的IP才能恢复。
    2.3 主机宕机,宕机前有部分数据未能及时同步到从机,切换IP后还会引入数据不一致的问题,降低了系统的可用性。
    2.4 redis 较难支持在线扩容,在集群容量达到上限时在线扩容会变得很复杂。为避免这一问题,运维人员在系统上线时必须确保有足够的空间,这对资源造成了很大的浪费。

17.redis与memcached区别?

  1. reids支持更丰富的类型(string、set、zset、list、hash),memcached仅支持string,redis比memcached更快,redis支持持久化
  2. Redis最大的亮点是支持数据持久化,它在运行的时候可以将数据备份在磁盘中,断电或重启后,缓存数据可以再次加载到内存中,只要Redis配置的合理,基本上不会丢失数据。

18.redis解决并发请求?

redis利用队列把并发访问变成串行访问,消除了传统的数据库的开销

19.redis有哪些结构时间复杂度较高的list?

哈希的实现编号可以是ziplist或者hashtable,ziplist编号的哈希对象采用压缩列表作为底层实现,每当有新的键值对要加入到hash对象的时候,程序会先将保存了键的压缩列表节点推入到压缩列表结尾,然后再将保存了值的压缩列表节点推入到压缩列表结尾,因此保存了同一键值对的两个节点总是紧挨在一起,保存的节点在前,保存值得节点在后,先添加到哈希对象的键值对会被放在压缩列表表头,后添加到哈希对象的键值对会被放在压缩列表的结尾。

20、使用过Redis分布式锁么,它是怎么实现的?

先拿setnx来争抢锁,抢到之后,再用expire给锁加一个过期时间防止锁忘记了释放。
Redis为单进程单线程模式,采用队列模式将并发访问变成串行访问,且多客户端对Redis的连接并不存在竞争关系,Redis中可以使用SETNX命令实现分布式锁。
当且仅当 key 不存在,将 key 的值设为 value。若给定的 key 已经存在,则 SETNX 不做任何动作
SETNX 是『SET if Not eXists』(如果不存在,则 SET)的简写。
返回值:设置成功,返回 1 。设置失败,返回 0 。
在这里插入图片描述

使用SETNX完成同步锁的流程及事项如下:使用SETNX命令获取锁,若返回0(key已存在,锁已存在)则获取失败,反之获取成功为了防止获取锁后程序出现异常,导致其他线程/进程调用SETNX命令总是返回0而进入死锁状态,需要为该key设置一个“合理”的过期时间释放锁,使用DEL命令将锁数据删除。

21、缓存和数据库之间的数据一致性问题?

分布式环境下非常容易出现缓存和数据库之间的一致问题,如果项目对数据是强一致性,那就不要用缓存,只能采用合适的策略来降低缓存和数据库不一致性的概率,而无法保证数据的强一致性,合适的策略包括合适的缓存更新策略,更新数据库后及时更新缓存,缓存更新失败后增加重试机制,例如MQ消息队列

总结:

如果你想到其他问题,欢迎留言,稍后我会将您留言的问题整理,以供大家学习参考

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/732638
推荐阅读
相关标签
  

闽ICP备14008679号