腾讯的redis面试问题,就这?

分布式redis锁

这个主要是有4个方面要解决。
1.互斥
2.不能死锁
3.容错性
4.重试机制
常见案例是这样的。
案例一:线程中master中活得锁后,master宕机了, 而集群使用主从异步的方式,在宕机的同时,另一个线程去获得锁,会产生两个线程获得锁。
案例二:有两个功能块都是需要上锁执行。 A模块需要调用B模块功能。此时会发生死锁问题。

from threading import Thread,Lock
import time
mutex=Lock()

class MyThread(Thread):
    def run(self):
        self.func1()
        
    def func1(self):
        mutex.acquire()
        print('\033[41m%s 拿到锁\033[0m' %self.name)
        self.func2() 
        mutex.release()

    def func2(self):
        mutex.acquire()
        print('\033[43m%s 拿到锁\033[0m' %self.name)
        mutex.release()

if __name__ == '__main__':
    t=MyThread()
    t.start()

在这里插入图片描述

为解决该问题,可以尝试以下方法入手。
redlock算法: 其核心思想就是给 n/2 +1 个机器加锁。这样即使有某少许机器宕机了,不影响锁的判断机制。 加锁是否超时来判断加锁是否成功,超时,则把该操作之前加的锁全解锁。

解决死锁问题,是引入一个新概念——可重入锁。
意思是让同一线程或者说同一资源块下可以重复访问这个锁。
实现原理是,先获取key对应的value,value默认一般会用uuid+threadid来取值。判断有value后,判断value是否与当前线程资源值匹配,若匹配,加锁时,则把锁的引用计数+1,没有key的时候则初始化为1;解锁时则-1,判断引用计数是否不大于0,来判断是否释放锁。

#修改上面代码,更换锁
from threading import Thread,Lock,RLock
import time
# mutex=Lock()
mutex = RLock() ##可重入锁
class MyThread(Thread):
    def run(self):
        self.func1()

在这里插入图片描述

重试机制的实现,原理是在value中增加一个锁过期的时间戳,每次设置锁失败的时候,用get获取该锁的过期时间,与当前时间进行比较,再进行判断即可。

redis过期策略

这个比较简单,就三种。
定时删除:指应用中给key设置过期时间时,同时设置删除时间。
惰性删除:指在获得key的时候判断是否过期,进行是否删除策略。
定时删除:指规定某个时间定时删除。

redis的缓存穿透,击穿,雪崩问题

这里先介绍下名词的意思。
缓存穿透:指大量请求不存在的key时,例如不存在的订单号时,不断访问数据库,数据库负荷。
缓存击穿:指在高并发时,key刚好过期,都需要连接数据库查询,数据库负荷。
缓存雪崩:指服务器重启或者大量缓存同一时间失效。

常见解决穿透方案就是:布隆过滤器了。大致原理是把可能出现的key都哈希到一个bitmap上。进行过滤

解决击穿的方案是在过期后,先给这个key设置个固定值,设置成功后,然后查询数据库,然后再把值覆盖上去。

解决缓存雪崩的问题,服务器重启,这个用集群去解决。大量缓存同一时间失效,则在设置过期时间的时候加个随机值。

redis高可用策略

redis高可用主要指的是4个点。
持久化
复制
哨兵机制
集群使用
复制和集群使用,这个就简单,就是多个redis服务,然后,同一份数据多备份一份。
哨兵机制,这个东西比较大,建议详查。哨兵机制是起自动化故障恢复作用。原理大致是:每个服务都有哨兵实例。
解决主节点挂了时,更换主节点。 原理每个哨兵都定时ping主节点,当失败是则主观判断主节点挂了,当有n/2 +1 个哨兵认为是挂的,则在剩下的节点中随机选举主节点。
持久化:指把数据放到磁盘中,一般有两个方式
RDB:复制当前数据库的数据到磁盘中
AOF:复制当前所有的数据库操作命令到磁盘中。
现在常用AOF。
毕竟AOF的优势显示在更实时。
RDB的优势则在于存储在磁盘的文件大小很小,恢复起来很快。

redis的位图操作

这个作用大都是处理大量需要存在redis中的key可以转化为序号,值为布尔值时,可以采用位图。
原理是利用二进制的0和1。序号表示位数。
假设 位图存的值是十进制是6,二进制则为110
序号为0的值则为0
序号为1的值为1
序号为2的值为1.
这样可以大大节约redis的使用资源。

猜你喜欢

转载自blog.csdn.net/weixin_43778491/article/details/107816546
今日推荐