Redis面试(一)

Redis概述
简单来说redis就是一个数据库,数据存储在内存,所以读写速度非常快。广泛应用于缓存,分布式锁等,redis支持事务,持久化,LUA脚本。LRU驱动事件,多种集群方案。

使用Redis做缓存
高性能:假设用户第一次访问数据库中的某些数据,过程会比较慢,因为是直接从硬盘上读取的,直接操作数据库。而将用户访问的数据存在缓存,下次直接从缓存中读取,相当于直接操作内存,速度非常快。如果数据库中的对应数据发生变化,更新缓存即可。
高并发:
将数据库中的数据存在缓存中,减少部分请求直接打到数据库,减少数据库压力。

Redis线程模型
redis内部使用文件事件处理器,file event handler,这个文件事件处理器是单线程的,所以redis才叫做单线程的模型。他采用io多路复用机制同时监听多个socket,根据socket上的事件来选择对应的事件处理器进行处理。

  • 多个socket
  • IO 多路复用程序
  • 文件事件分派器
  • 事件处理器(连接应答处理器、命令请求处理器、命令回复处理器)

Redis和memcached区别

  1. redis支持丰富的数据类型,除了简单的k/v类型外,还支持list,set,zset,hash。memcache支持string。
  2. redis支持数据的持久化。
  3. redis原生支持集群。
  4. memcache多线程,非阻塞io复用;redis单线程,多路io复用

Redis设置过期时间
redis可以对某个key设置过期时间,即这个key的存活时间,到期后使用定期删除+惰性删除。
定期删除:redis每个100ms就随机抽取设置了过期时间的key,判断是否过期,如果过期则删除。如果不是随机抽取,假设redis存在几十万个key,那每次就要遍历所以设置过期时间的key,cpu负载。
惰性删除:假设定期删除没有把过期了的key删掉,那么等下次去查那个key的时候才会把它删除掉。

Redis内存淘汰机制
volatile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰
volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰
volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰
allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的key(这个是最常用的)
allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
no-eviction:禁止驱逐数据,也就是说当内存不足以容纳新写入数据时,新写入操作会报错。
volatile-lfu:从已设置过期时间的数据集(server.db[i].expires)中挑选最不经常使用的数据淘汰
allkeys-lfu:当内存不足以容纳新写入数据时,在键空间中,移除最不经常使用的key

Redis持久化机制
RDB(快照):redis可以通过创建快照来获得存储在内存里面的数据在某个时间点上的副本。redis可以对快照进行备份,复制到其他服务器以实现具有相同的服务器副本(主从结构)。或者留在本地以便重启服务器使用。
save 900 1 #在900秒(15分钟)之后,如果至少有1个key发生变化,Redis就会自动触发BGSAVE命令创建快照。
AOF(append-only file追加文件):与快照持久化相比,AOF持久化 的实时性更好,可以通过appendonly参数开启:appendonly yes,开启AOF持久化后每执行一条会更改Redis中的数据的命令,Redis就会将该命令写入硬盘中的AOF文件。AOF文件的保存位置和RDB文件的位置相同,都是通过dir参数设置的,默认的文件名是appendonly.aof。
aof持久化方式:
appendfsync always #每次有数据修改发生时都会写入AOF文件,这样会严重降低Redis的速度
appendfsync everysec #每秒钟同步一次,显示地将多个写命令同步到硬盘(一般使用每秒同步)
appendfsync no #让操作系统决定何时进行同步

redis4.0开始支持混合持久化(参数:aof-use-rdb-preamble)

缓存雪崩
同一时间大面积的key失效,后面的请求都打到数据库上,造成数据库但时间内承受大量请求而崩掉。
解决方案:
事前:尽量保证整个redis集群的高可用,选择合适的内存淘汰策略。
事中:使用本地缓存ehcahce缓存+hystrix限流&降级,避免mysql崩掉。
事后:利用redis持久化机制保存的数据尽快恢复缓存。

缓存穿透
大量的请求key根本不存在缓存中,导致请求直接打在数据库上,根本没有经过缓存这一层。
解决方案:
1.缓存无效key:如果缓存和数据库中查不到某个key的数据就直接写到缓存中并设置过期时间,过期时间尽量小一点,但是此方案会导致缓存中存在大量的无效key,比如黑客恶意攻击。
2.布隆过滤器:可以判断某个数据是否存在海量数据中。具体做法,把所有可能存在的请求值放在布隆过滤器中,请求过来先判断过滤器中是否存在,如果不存在则返回错误信息。

布隆过滤器实现:
由一个位数组和一系列哈希函数组成的数据结构。
优点:空间小且效率高。(位数组中的每个元素都只占用 1 bit ,并且每个元素只能是 0 或者 1。这样申请一个 100w 个元素的位数组只占用 1000000Bit / 8 = 125000 Byte = 125000/1024 kb ≈ 122kb 的空间。)
缺点:返回结果存在概率性。
工作原理:当一个元素加入布隆过滤器的时候,会使用当中的hash函数进行计算,得到哈希值,有几个哈希函数就得到几个哈希值。根据得到的哈希值在位数组中对应下标的值置为1.
当要判断某个元素是否存在布隆过滤器中的时候,对元素进行相同的哈希计算,对得到的哈希值对应在为数组下标中的元素判断是否为1,如果全为1,则存在,如果由一个不为1,则元素不在过滤器中。
不同的字符串可能哈希出来的位置相同,这种情况我们可以适当增加位数组大小或者调整我们的哈希函数。
布隆过滤器说某个元素存在,小概率会误判。布隆过滤器说某个元素不在,那么这个元素一定不在。

使用场景
判断给定数据是否存在:比如判断一个数字是否在于包含大量数字的数字集中(数字集很大,5亿以上!)、 防止缓存穿透(判断请求的数据是否有效避免直接绕过缓存请求数据库)等等、邮箱的垃圾邮件过滤、黑名单功能等等。
去重:比如爬给定网址的时候对已经爬取过的 URL 去重。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值