备战面试之Redis

讲一讲你在项目中是如何使用Redis的(结合项目经历谈一谈Redis)

应用

我在项目中使用Redis的目的是用作缓存以及数据库使用的,我的项目是一个仓库管理系统,系统有一个缓存模块,用于保存一些实时数据,比如厂房中各个库位当前的库存情况、各设备当前的工作状态、以及当前正在执行的作业指令等,这些数据经常根据作业情况实时变化,所以我把它们直接在在缓存中处理,并且为了在服务器重启之后能够恢复断线之前的厂房的库存以及工作状态,也需要将这些数据进行持久化,在这里我希望缓存模块能够快速的处理数据以及具有持久化的功能,因此我使用Redis作为缓存和数据库,在这里我想讲一下Redis具有高性能的原因以及它的持久化机制实现原理。

高性能

Redis高性能的主要原因有三点,它是基于内存的操作、高效的数据结构以及使用非阻塞IO模型,我重点说一下Redis使用的数据结构以及非阻塞IO模型。

数据结构

Redis中的数据是以Key/Value的形式存储的,为了实现从键到值的快速访问,Redis使用一个哈希表来保存所有键值对,哈希表底层使用数组+链表实现,哈希表的查找过程依赖于哈希计算,无论数据量有多少,只需要进行一次哈希计算就可以找到对应的键,因此哈希表的查找效率很高,在根据键值计算哈希值时,哈希冲突的问题是不可避免的,所谓哈希冲突就是不同的键具有相同的哈希值,如果只采用数组存储就会覆盖掉原来存储的数据,因此引入链表,将具有相同哈希值的键值对通过链表串联在一起再存到数组中。

  • String: 简单动态字符串
  • List:可以快速地查找首尾元素,对首尾元素进行修改,非首尾元素的查找以及修改复杂度较高,由于这个特性,此数据类型十分适合作为一个FIFO队列使用,我在项目中使用这种数据类型存储作业指令,指令按照下发顺序排队依次执行,用List可以快速的实现指令的下发以及完成,底层使用双向链表和压缩列表实现。
  • Hash:采用键值映射的方法存储,可以快速地查找元素,但是集合中的元素是无序的,如果需要获取有序集合则需要先查询,再对得到的集合排序,底层采用哈希表和压缩列表的实现。
  • Set:Set不允许集合中有重复元素,同样能够快速地查找元素,集合中的元素是无序的,其底层使用哈希表和整数数组实现。
  • Sorted Set:和Set类似,集合中同样不允许出现重复元素,但是Sorted Set中的元素是有序的,底层使用哈希表和跳表实现。
非阻塞IO模型

Redis对数据的读写操作时单线程的,之所以没有采用多线程提升性能是因为影响Redis读写效率的主要原因是内存大小以及网络传输速率,而并非CPU,使用多线程模型会增加多个线程之间上下文切换带来的额外开销,同时还要面临共享资源的并发控制问题,因此综合考量,Redis直接采用单线程模式。那么再单线程模式下Redis依然能够具高性能,除了由于其大部分操作直接在内存中完成,以及使用高效的数据结构之外,还得益于使用了多路复用机制提高性能。 所谓多路复用机制,就是指一个线程处理多个IO流,简单来说在Redis只运行单线程的情况下,该机制允许内核中同时存在多个监听套接字和已连接套接字,内核会一直监听这些套接字上的连接请求和数据请求,一旦请求到达,就会交给Redis线程处理,这就实现了一个Redis线程处理多个IO流的效果。为了能在请求到达时通知到Redis线程,该机制提供了基于事件的回调机制,即针对不同事件的发生调用相应的处理函数。这样一来Redis线程不会阻塞在某一个特定的监听或者已连接套接字上,也就是说不会阻塞在某一个特定的客户端请求处理上,所以Redis可以同时和多个客户端连接并处理请求,从而提升并发性。

持久化机制

讲完了Redis在单线程的模式下仍然具有高性能的原因后,我想讲一下Redis的持久化机制,Redis的持久化机制主要有两大机制,分别是AOF日志和RDB快照。

AOF日志

Redis将已完成的指令写入到日志中,日志是存储在磁盘上的,当Redis重启时,从磁盘中读取日志,并将里面的指令依次执行一遍,那么重启之前的数据就重新加载到缓存中了。
使用AOF日志持久化将面临两个问题,一个是什么时候将已完成的指令写入日志中,针对这个问题AOF机制提供了三种写回策略:

  • Always,同步写回:每个写命令执行完,立马同步地将日志协会磁盘,这种策略可以做到基本不丢数据,但是他在每个写命令后都有一个慢速的写磁盘操作,会影响主线程性能。
  • No,操作系统控制写回:每个命令执行完,只是先把日志写到AOF文件的内存缓冲区,由操作系统决定何时将缓冲区内容写回磁盘。此种方式避免了同步写回地性能开销,减少了对系统性能的影响,但落盘时机已经不在Redis手中了,一旦宕机,对应的数据就会丢失。
  • Everysec,每秒写回:每个命令执行完,只是先把日志写到AOF文件的内存缓冲区,每隔一秒把缓冲区中的内容写入磁盘。这种策略同样避免了同步写回地性能开销,但如果发生宕机,上一秒内为落盘地命令操作仍然会丢失丢失。
    综合考量,当需要系统具有高可靠性,不允许数据丢失,采用同步写回,想要获取高性能就选择操作系统控制写回,如果一点数据丢失有希望性能不要受到太大影响就选择每秒写回。
    使用AOF日志持久化需要面临的另外一个问题是是AOF文件过大带来的性能问题,针对这个问题,AOF提供了重写机制,也就是Redis根据内存中的当前数据创建一个新的AOF文件替换原来较大的文件,也就是说读取内存中的所有键值对,然后生成命令记录它的写入,最后用新的日志文件替换掉旧日志。而为了使重写日志的操作不会阻塞主线程,重写的过程由后台线程完成。
RDB快照

用AOF方法进行故障回复的时候。需要注意把操作日志都执行一遍,这个过程在操作日志非常多的时候会恢复的很缓慢,为了既保证可靠性又能够在宕机时实现快速的恢复,Redis提供了RDB快照的方式进行持久化。
与AOF不同的是,RDB直接记录某一时刻内存中的数据而不是操作命令,所以在做数据恢复时,我们可以直接把RDB文件读入内存中,很快完成恢复。在做RDB快照时,需要我们考虑多久做一次快照,如果发生宕机时,最近一次快照之后的数据将会全部丢失,那么就需要尽量缩短两次快照之间的时间间隔,这样又会造成拼房的进行快照造成的性能开销。为了解决这个问题,提出一种混合使用AOF日志和RDB快照的方法,简单来说就是RDB快照以一定的频率执行,两次快照之间使用AOF日志记录这期间的所有操作命令,每次快照之后将AOF日志清空并重新记录,这样一来快照不需要频繁的执行,AOF日志也只需要记录两次快照之间的操作,就不会出现文件过大的情况,也就是避免了重写的开销。

怎么防止缓存击问题

布隆过滤器的原理是什么?优缺点是什么?缺陷是什么?

全部评论

相关推荐

太难了,双9bg也被刷
投递韶音科技等公司10个岗位
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务