烟台市建设局网站,建设项目竣工验收公示网站,赵艳红网站建设规划,网站备案 不备案【JavaGuide面试总结】Redis篇中1.Redis 单线程模型了解吗#xff1f;2.Redis6.0 之后为何引入了多线程#xff1f;3.Redis 是如何判断数据是否过期的呢#xff1f;4.过期的数据的删除策略了解么#xff1f;5.Redis 内存淘汰机制了解么#xff1f;6.什么是 RDB 持久化2.Redis6.0 之后为何引入了多线程3.Redis 是如何判断数据是否过期的呢4.过期的数据的删除策略了解么5.Redis 内存淘汰机制了解么6.什么是 RDB 持久化7.RDB 创建快照时会阻塞主线程吗8.什么是 AOF 持久化9.AOF 重写了解吗10.如何选择 RDB 和 AOF11.缓存常用的3种读写策略Cache Aside Pattern旁路缓存模式Read/Write Through Pattern读写穿透Write Behind Pattern异步缓存写入1.Redis 单线程模型了解吗
Redis 基于 Reactor 模式设计开发了一套高效的事件处理模型这套事件处理模型对应的是 Redis 中的文件事件处理器file event handler。由于文件事件处理器file event handler是单线程方式运行的所以我们一般都说 Redis 是单线程模型。
既然是单线程那怎么监听大量的客户端连接呢
Redis 通过 IO 多路复用程序 来监听来自客户端的大量连接或者说是监听多个 socket它会将感兴趣的事件及类型读、写注册到内核中并监听每个事件是否发生。
这样的好处非常明显 I/O 多路复用技术的使用让 Redis 不需要额外创建多余的线程来监听客户端的大量连接降低了资源的消耗。
文件事件处理器file event handler主要是包含 4 个部分
多个 socket客户端连接IO 多路复用程序支持多个客户端连接的关键文件事件分派器将 socket 关联到相应的事件处理器事件处理器连接应答处理器、命令请求处理器、命令回复处理器 2.Redis6.0 之后为何引入了多线程
Redis6.0 引入多线程主要是为了提高网络 IO 读写性能因为这个算是 Redis 中的一个性能瓶颈Redis 的瓶颈主要受限于内存和网络。
虽然Redis6.0 引入了多线程但是 Redis 的多线程只是在网络数据的读写这类耗时操作上使用了执行命令仍然是单线程顺序执行。因此你也不需要担心线程安全问题。
Redis6.0 的多线程默认是禁用的只使用主线程。如需开启需要设置IO线程数 1需要修改 redis 配置文件 redis.conf
io-threads 4 # 设置1的话只会开启主线程官网建议4核的机器建议设置为2或3个线程8核的建议设置为6个线程开启多线程后默认只会使用多线程进行IO写入writes即发送数据给客户端如果需要开启多线程IO读取reads同样需要修改 redis 配置文件 redis.conf :
io-threads-do-reads yes开启多线程读并不能有太大提升因此一般情况下并不建议开启 3.Redis 是如何判断数据是否过期的呢
Redis 通过一个叫做过期字典可以看作是 hash 表来保存数据过期的时间。过期字典的键指向 Redis 数据库中的某个 key(键)过期字典的值是一个 long long 类型的整数这个整数保存了 key 所指向的数据库键的过期时间 4.过期的数据的删除策略了解么
常用的过期数据的删除策略就两个
惰性删除 只会在取出 key 的时候才对数据进行过期检查。这样对 CPU 最友好但是可能会造成太多过期 key 没有被删除。定期删除 每隔一段时间抽取一批 key 执行删除过期 key 操作。并且Redis 底层会通过限制删除操作执行的时长和频率来减少删除操作对 CPU 时间的影响。
定期删除对内存更加友好惰性删除对 CPU 更加友好。两者各有千秋所以 Redis 采用的是 定期删除惰性/懒汉式删除 。
但是仅仅通过给 key 设置过期时间还是有问题的。因为还是可能存在定期删除和惰性删除漏掉了很多过期 key 的情况。这样就导致大量过期 key 堆积在内存里然后就 Out of memory 了。 Redis 使用内存淘汰机制防止 Out of memory 发生 5.Redis 内存淘汰机制了解么
Redis 提供 6 种数据淘汰策略
volatile-lruleast recently used从已设置过期时间的数据集server.db[i].expires中挑选最近最少使用的数据淘汰volatile-ttl从已设置过期时间的数据集server.db[i].expires中挑选将要过期的数据淘汰volatile-random从已设置过期时间的数据集server.db[i].expires中任意选择数据淘汰allkeys-lruleast recently used当内存不足以容纳新写入数据时在键空间中移除最近最少使用的 key这个是最常用的allkeys-random从数据集server.db[i].dict中任意选择数据淘汰no-eviction禁止驱逐数据也就是说当内存不足以容纳新写入数据时新写入操作会报错。 6.什么是 RDB 持久化
Redis 可以通过创建快照来获得存储在内存里面的数据在某个时间点上的副本。Redis 创建快照之后可以对快照进行备份可以将快照复制到其他服务器从而创建具有相同数据的服务器副本Redis 主从结构主要用来提高 Redis 性能还可以将快照留在原地以便重启服务器的时候使用。 7.RDB 创建快照时会阻塞主线程吗
Redis 提供了两个命令来生成 RDB 快照文件
save : 主线程执行会阻塞主线程bgsave : 子线程执行不会阻塞主线程默认选项。 8.什么是 AOF 持久化
开启 AOF 持久化后每执行一条会更改 Redis 中的数据的命令Redis 就会将该命令写入到内存缓存 server.aof_buf 中然后再根据 appendfsync 配置来决定何时将其同步到硬盘中的 AOF 文件。
在 Redis 的配置文件中存在三种不同的 AOF 持久化方式它们分别是
appendfsync always # 每次有数据修改发生时都会写入AOF文件,这样会严重降低Redis的速度
appendfsync everysec # 每秒钟同步一次显式地将多个写命令同步到硬盘
appendfsync no # 让操作系统决定何时进行同步9.AOF 重写了解吗
当 AOF 变得太大时Redis 能够在后台自动重写 AOF 产生一个新的 AOF 文件这个新的 AOF 文件和原有的 AOF 文件所保存的数据库状态一样优化命令执行去除无效但体积更小。
通过执行bgrewriteaof命令可以让AOF文件执行重写功能用最少的命令达到相同效果。 Redis也会在触发阈值时自动去重写AOF文件。阈值也可以在redis.conf中配置 10.如何选择 RDB 和 AOF
RDB 比 AOF 优秀的地方
RDB 文件存储的内容是经过压缩的二进制数据 保存着某个时间点的数据集文件很小适合做数据的备份灾难恢复。AOF 文件存储的是每一次写命令通常会必 RDB 文件大很多。当 AOF 变得太大时Redis 能够在后台自动重写 AOF。新的 AOF 文件和原有的 AOF 文件所保存的数据库状态一样但体积更小使用 RDB 文件恢复数据直接解析还原数据即可不需要一条一条地执行命令速度非常快。而 AOF 则需要依次执行每个写命令速度非常慢。也就是说与 AOF 相比恢复大数据集的时候RDB 速度更快。
AOF 比 RDB 优秀的地方
RDB 的数据安全性不如 AOF没有办法实时或者秒级持久化数据。生成 RDB 文件的过程是比繁重的 虽然 BGSAVE 子进程写入 RDB 文件的工作不会阻塞主线程但会对机器的 CPU 资源和内存资源产生影响严重的情况下甚至会直接把 Redis 服务干宕机。AOF 支持秒级数据丢失取决 fsync 策略如果是 everysec最多丢失 1 秒的数据仅仅是追加命令到 AOF 文件操作轻量RDB 文件是以特定的二进制格式保存的并且在 Redis 版本演进中有多个版本的 RDB所以存在老版本的 Redis 服务不兼容新版本的 RDB 格式的问题。AOF 以一种易于理解和解析的格式包含所有操作的日志。 11.缓存常用的3种读写策略
Cache Aside Pattern旁路缓存模式
Cache Aside Pattern 是我们平时使用比较多的一个缓存读写模式比较适合读请求比较多的场景。
Cache Aside Pattern 中服务端需要同时维系 db 和 cache并且是以 db 的结果为准。
下面我们来看一下这个策略模式下的缓存读写步骤。
写
先更新 db然后直接删除 cache 。 读 :
从 cache 中读取数据读取到就直接返回cache 中读取不到的话就从 db 中读取数据返回再把数据放到 cache 中。 现在我们再来分析一下 Cache Aside Pattern 的缺陷。
缺陷 1首次请求数据一定不在 cache 的问题
解决办法可以将热点数据可以提前放入 cache 中。
缺陷 2写操作比较频繁的话导致 cache 中的数据会被频繁被删除这样会影响缓存命中率 。
解决办法
数据库和缓存数据强一致场景 更新 db 的时候同样更新 cache不过我们需要加一个锁/分布式锁来保证更新 cache 的时候不存在线程安全问题。可以短暂地允许数据库和缓存数据不一致的场景 更新 db 的时候同样更新 cache但是给缓存加一个比较短的过期时间这样的话就可以保证即使数据不一致的话影响也比较小。
Read/Write Through Pattern读写穿透
Read/Write Through Pattern 中服务端把 cache 视为主要数据存储从中读取数据并将数据写入其中。cache 服务负责将此数据读取和写入 db从而减轻了应用程序的职责。
写Write Through
先查 cachecache 中不存在直接更新 dbcache 中存在则先更新 cache然后 cache 服务自己更新 db同步更新 cache 和 db 读(Read Through)
从 cache 中读取数据读取到就直接返回 。读取不到的话先从 db 加载写入到 cache 后返回响应。 Write Behind Pattern异步缓存写入
Write Behind Pattern 和 Read/Write Through Pattern 很相似两者都是由 cache 服务来负责 cache 和 db 的读写。
但是两个又有很大的不同Read/Write Through 是同步更新 cache 和 db而 Write Behind 则是只更新缓存不直接更新 db而是改为异步批量的方式来更新 db。
很明显这种方式对数据一致性带来了更大的挑战比如 cache 数据可能还没异步更新 db 的话cache 服务可能就就挂掉了。
Write Behind Pattern 下 db 的写性能非常高非常适合一些数据经常变化又对数据一致性要求没那么高的场景比如浏览量、点赞量。