当前位置: 首页 > 后端技术 > Java

Java开发面试:Redis高并发处理

时间:2023-04-01 22:09:12 Java

1.Redis常见的性能问题和解决方法有哪些?Redis常见的性能问题及解决方法如下:Master最好不要做任何持久化的工作,比如RDB内存快照,AOF日志文件;如果数据比较重要,Slave会启用AOF备份数据,策略设置为每秒同步一次;主从复制的速度和连接的稳定性,Master和Slave在同一个局域网内最好;尽量避免在高压下向主库添加从库;主从复制不要使用图结构,使用单向链表结构更稳定,即:Master<-Slave1<-Slave2<-Slave3….;这种结构便于解决单点故障问题,实现Master换Slave。如果Master挂掉了,可以马上让Slave1成为Master,其他不变。2.MySQL有2000万条数据,Redis只有2000万条数据。如何保证Redis中的数据都是热数据?因为内存空间有限,Redis淘汰机制主要是解决在某个时间点,Redis中有很多过期key,定时删除策略java训练随机抽查没有发现,没有懒惰删除策略。过期键占用内存。如果内存只能存储20w的数据,而我们需要存储2000w的数据,我们自然需要删除或覆盖多余的数据,以保证内存中存储的数据都是热数据。因此,当Redis内存数据集的大小上升到一定数量时,就会执行数据淘汰策略。3、假设Redis中有1亿个key,其中10w个key以固定的已知前缀开头,如何全部找到?我们可以使用keys命令和scan命令,但我们可能会发现使用scan会更好。《1.使用keys命令》直接使用keys命令查询,但是如果在生产环境中使用,就会出现问题。keys命令遍历查询,查询的时间复杂度为O(n)。数据量越大,查询时间越长。而且,Redis是单线程的。keys命令会导致线程阻塞一段时间,从而导致在线的Redis暂停一段时间,直到keys执行完毕才会恢复。这在生产环境中是不允许的。另外需要注意的是,这个命令没有分页功能,它会一次性查询所有符合条件的键值,你会发现查询结果非常大,输出的信息也非常多。所以不推荐使用该命令。《2.使用scan命令》scan命令可以实现和keys一样的匹配功能,但是scan命令在执行过程中不会阻塞线程,而且搜索到的数据可能重复,需要客户端操作去重。因为scan是通过游标来查询的,所以不会造成Redis中的假死问题。Redis查询过程中,游标会返回给客户端。如果返回了一次空值,游标不为0,说明遍历还没有结束,客户端继续遍历查询。在scan的检索过程中,删除的元素不会被查询到,但是如果在迭代过程中修改了某些元素,scan不能保证一定会查询到对应的元素。相对来说,scan命令比keys命令查找时间更长。4、什么是缓存穿透?如何处理?大量的请求瞬间涌入系统,但是这个数据在Redis中是不存在的,所有的请求都落在了数据库上,杀死了数据库。造成这种情况的原因包括系统设计不合理,缓存数据更新不及时,或者爬虫等恶意攻击。解决方案是:“1.使用Bloomfilter”将所有查询参数存储在一张位图中,然后在查询缓存前找一个新的位图验证参数。如果已验证位图中存在,则执行底层缓存数据查询。如果查询参数在位图中不存在,则会被拦截,不再进行缓存数据查询。《2.缓存空对象》如果从数据库查询的结果为空,结果还是缓存了,那么在使用key获取数据的时候,即使数据不存在,Redis也可以直接返回结果,避免多次访问数据库。但是缓存空值的缺点是,如果有黑客恶意随机访问,导致缓存过多的空值,可能会造成内存空间的大量浪费。但是你也可以为这些数据设置一个很短的过期时间来控制;如果查询的key对应的Redis缓存空值还没有过期,此时数据库有新的数据,那么就会出现数据库和缓存数据不一致的情况。但是可以保证,当数据库有数据的时候,更新缓存来解决。5、什么是缓存雪崩?如何处理?缓存雪崩是指当大量缓存失效时,大量请求直接请求数据库,导致数据库服务器无法抗拒请求或挂掉的情况。这时候网站经常会出现502错误,导致网站无法访问。在防止缓存雪崩时,建议遵循以下原则:合理规划缓存的过期时间,可以在缓存时间中加入一个随机数,防止统一时间过期;合理评估数据库的负载压力,有利于在合理范围内进行部分缓存,数据库也可以正常访问;对数据库的过载保护或应用层限流,这种情况一般是在网站流量大、高并发,服务器整体无法承受时可以采用的限流保护措施;最后,还可以考虑多级缓存设计,实现缓存的高可用。6、如果有大量key同时需要设置过期,需要注意什么?如果大量key同时过期,可能会在同一秒从数据库中获取数据,这会给数据库带来很大的压力,导致数据库崩溃,导致系统出现502问题。它也可能同时失败。在那一刻,不需要访问数据库。如果压力不够大,Redis会出现短暂的卡顿问题。所以,为了防止这种问题的发生,最好给数据的过期时间加上一个随机值,让过期时间更加分散。7、Redis哨兵和集群有什么区别?RedisSentinel的作用是管理多个Redis服务器,提供监控、提醒、故障自动转移等功能。Sentinel可以保证当主服务器挂掉时,可以选择其中一台从服务器作为主服务器,其他的从服务器转移到新的主机上。RedisSentinel的主要功能有:集群监控:监控Redis集群的主从进程,判断其是否正常工作。消息通知:如果Redis实例出现故障,Sentinel可以发送告警消息通知管理员。Failover:如果宿主(master)节点挂了,可以自动转移到从(slave)节点。配置中心:当出现故障时,故障转移后,配置中心会通知客户端新的主机(master)地址。Redis集群的作用是解决单个Redis容量有限的问题,将数据按照一定的规则分布到多台机器上。每秒访问内存不限于单台服务器,可以受益于分布式集群的高扩展性。.8、Redis哨兵的作用是什么?Sentinel是Redis集群架构中非常重要的一个组件。其主要功能如下:集群监控,负责监控RedisMaster和Slave进程是否正常工作;消息通知,如果某个Redis实例出现故障,Sentinel负责发送消息作为告警通知给Administrator;failover,如果Master节点挂了,会自动转移到Slave节点;配置中心,如果发生failover,通知Client新的Master地址。9、请介绍几个可能导致Redis阻塞的原因。Redis阻塞的原因主??要有内因和外因:“1.内部原因”如果Redis宿主机的CPU负载过高,也会导致系统崩溃;数据持久化优化占用资源过多;RedisAPI或指令使用不合理,导致Redis出现问题。《2.外部原因》外部原因主要是服务器的原因,比如切换过程中服务器的CPU线程竞争太激烈,内存问题,网络问题等。10.你了解Redis的同步机制吗?Redis可以使用主从同步和从从同步。第一次同步时,master节点执行一次bgsave,同时将后续的修改操作记录到内存缓冲区中。完成后将整个RDB文件同步到复制节点,复制节点接受后将RDB镜像加载到内存中。加载完成后,通知主节点将修改后的操作记录同步到复制节点进行重放,完成同步过程。11、Redis集群中bigkey和hotkey如何处理?对于bigkey,先分析业务中有大key值是否合理。如果没有,我们可以将它们拆分成多个小存储。或者看看能不能用其他存储介质来存储这种大key,解决占用内存空间大的问题。对于hotkey,我们可以在其他机器上复制这个key的备份,这样当请求进来的时候,我们就可以随机访问每台机器上的缓存。那么剩下的问题就是如何将请求平均分配到每台机器上。12、如何发现Redis阻塞的异常情况?可以从以下两方面着手准备:《1.使用Redis自带的监控系统》使用Redis自带的监控系统监控CPU、内存、磁盘、命令耗时等阻塞问题。当监控系统发现各监控指标异常时,发出告警。《2.使用应用服务监控》当Redis被阻塞时,应用响应时间会延长,应用可以感知到问题并向管理员发出警报。13.你知道Redis的分区实现吗?客户端分区意味着客户端已经决定了数据存储在哪个Redis节点或从哪个Redis节点读取。大多数客户端已经实现了客户端分区。代理分区是指客户端向代理发送请求,由代理决定从哪个节点写入或读取。proxy根据分区规则决定请求哪些Redis实例,然后根据Redisresponse返回给client。Redis和Memcached的一种代理实现是Twemproxy。查询路由是指客户端随机请求任意一个Redis实例,然后Redis将请求转发给正确的Redis节点。RedisCluster实现了一种混合形式的查询路由,但不是直接将请求从一个Redis节点转发到另一个,而是在客户端的帮助下将它们直接重定向到正确的Redis节点。14、Redis集群之间的复制方式是什么?在了解Redis的复制方式之前,先了解一下主从复制(Master-SlaveReplication)的工作原理,具体来说:从节点服务启动并连接到主节点后,会主动发送一个SYNC命令;master服务主节点收到同步命令后,会启动后台保存进程,收集所有收到的修改数据集的命令。后台进程执行完毕后,Master会把整个数据库文件传给Slave,完成一次完整的同步;Slave将从节点服务端接收到数据库文件数据后,保存并加载到内存中;之后Master主节点继续将收集到的所有修改命令和新的修改命令依次发送给Slave,Slave将执行本次数据修改命令,从而实现最终的数据同步。整个执行过程使用异步复制进行复制。15、什么是数据库缓存双写一致性?当一条数据需要更新时,因为不可能同时更新数据库和缓存,那么此时读取数据就不可避免的会出现数据不一致的情况,而现场的系统是绝对不允许出现数据不一致的的金融交易。解决方法:读的时候,先读缓存。如果没有缓存,则读取数据库,然后取出数据放入缓存,同时返回响应。更新时,先更新数据库,再删除缓存。16、为什么要对Redis进行分区?分区可以让Redis管理更大的内存,Redis将可以使用所有机器的内存。不分区,最多只能使用一台机器的内存。分区使得Redis的计算能力可以通过简单地增加计算机来成倍增加,Redis的网络带宽也会随着计算机和网卡的增加而翻倍。17、分布式Redis应该在前期做还是后期规模上来了,为什么?为了防止以后扩展困难,最好的办法是一开始就使用分布式。即使只有一台服务器,Redis也可以从一开始就以分布式的方式运行,使用分区,在同一台服务器上启动多个实例。一开始比较麻烦,但是当数据不断增长,需要更多的Redis服务器时,只需要将Redis实例从一种服务迁移到另一种服务即可,无需考虑重新分区的问题。一旦添加了另一台服务器,只需要将一半的??Redis实例从第一台机器迁移到第二台机器。18、如果有大量key同时需要设置过期,需要注意什么?如果大量key的过期时间设置的过于密集,redis在过期时可能会出现短暂的卡顿。一般需要在时间上加上一个随机值,使过期时间更加分散。19.什么是分布式锁?效果如何?分布式锁是一种控制分布式系统之间共享资源同步访问的方法。在单机或者单进程环境下,在多线程并发的情况下,使用锁来保证一个代码块在同一时间只能被一个线程执行。示例包括Java的Synchronized关键字和Reentrantlock类。分布式锁的作用是当多个进程不在同一个系统中时,可以使用分布式锁来控制多个进程对资源的访问。20.分布式锁如何实现?Memcached可以用来实现分布式锁:Memcached提供原子操作指令add,线程获取锁。如果key已经存在,则添加失败,获取锁也失败。也可以使用Redis来实现分布式锁:Redis的setnx命令是一个原子操作命令。只有当key不存在时,set才会成功。类似于Memcached的add方法。也可以使用ZooKeeper分布式锁:使用ZooKeeper的顺序临时节点实现分布式锁和等待队列。还有Chubby实现分布式锁:Chubby底层使用Paxos共识算法实现粗粒度的分布式锁服务。21.介绍一下分布式锁实现的注意事项?分布式锁的实现需要保证以下几点:互斥:任何时候只有一个资源可以获得锁;容灾:在锁释放不成功的情况下,可以在一定时限内恢复锁的正常功能;统一的弹性:锁定和解锁确保相同的资源用于操作。文章来源:YP肖战