2020面试题总结——Redis篇1、Redis的优势。
?速度快,因为数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1)。
支持丰富的数据类型,支持string,list,set,zset和hash。
支持事务性。操作都是原子性,所谓的原子性就是对数据的更改要么全部执行,要么全部不执行。(这块需要注意与之前MySQL不同)丰富的特性,可用于缓存,消息队列,按key设置过期时间,过期后将自动删除。
???2、Redis的数据结构都有哪些。
Redis支持五种ValueType,其底层实现的编码数据结构有8种:
????????SDS-simplesynamicstring-支持自动动态扩容的字节数组list-平平无奇的链表
dict-使用双哈希表实现的,支持平滑扩容的字典zskiplist-附加了后向指针的跳跃表intset-用于存储整数数值集合的自有结构
ziplist-一种实现上类似于TLV,但比TLV复杂的,用于存储任意数据的有序序列的数据结构
quicklist-一种以ziplist作为结点的双链表结构zipmap-一种用于在小规模场合使用的轻量级字典结构
衔接\底层数据结构\与\Type\的桥梁的,则是Redis实现的另外一种数据结构:redisObject.。
Redis中的Key与Value在表层都是一个redisObject实例,故该结构有所谓的\类型\即是ValueType.对于每一种ValueType类型的redisObject,其底层至少支持两种不同的底层数据结构来实现.以应对在不同的应用场景中,Redis的运行效率,或内存占用.
对于具体数据结构介绍,建议看《Redis设计与实现》第一部分,或者看这篇文章,面试官:你看过Redis数据结构底层实现吗?3、Redis的使用要注意什么。
现阶段主要从数据存储和数据获取两个方面来说明开发时的注意事项:
数据存储:因为内存空间的局限性,注定了能存储的数据量有限,如何在有限的空间内存储跟多的数据信息是我们应该关注的。Redis内存存储的都是键值对,那么如何减少键值对所占据的内存空间就是空间优化的本质。比如可以在清晰表达业务含义的基础上尽可能缩减key的字符长度,也可以当value是图片、大文本等大数据信息时,借助压缩工具压缩之后再存入Redis中。
数据查询:Redis是一种数据库,和其他数据库一样,操作时也需要有连接对象,连接对象的创建和销毁也需要耗费资源,复用连接对象很有必要,所以推荐使用连接池来进行管理(比如在自己项目中用JedisPool来获取Redis连接)。此外,对于连续多次的查询,可以使用mget(针对string类型查询)/hmget(针对Hash类型查询),将多次请求合并为一次,提高响应速度。4、Redis的事务性。
Redis通过MULTI、EXEC、WATCH等命令来实现事务(transaction)功能。事务提供了一种将多个命令请求打包,然后一次性、按顺序地执行多个命令的机制,并且在事务执行期间,服务器不会中断事务而改去执行其他客户端的命令请求,它会将事务中的所有命令都执行完毕后,然后才去处理其他客户端的命令请求。
事务的生命周期为:
???事务开始:使用MULTI开启一个事务(自己项目中,采用jedis.multi()来返回一个事务Transaction,后续可以在此事务上进行操作)命令入队:在开启事务的时候,每次操作的命令将会被插入到一个队列中,同时这个命令并不会被真的执行。事务执行:EXEC命令进行提交事务
Redis事务具有的性质:
??单独的隔离操作:事务中所有命令都会被序列化、按顺序执行,在执行过程中不会被其他客户端发送来的命令打断。
没有隔离级别的概念:队列中的命令在事务没有被提交之前不会被实际执行。
在Redis中,事务总是具有原子性、一致性和隔离性。当Redis运行在某种特定的持久化模式(开启AOF和RDB服务)下时,事务也具有持久性。着重讲一下原子性。
对于Redis的事务功能来说,事务队列中的命令要么就全部执行,要不就一个都不执行。从这点来说,事务具有原子性。但这个执行失败的条件是指命令入队出错(比如命令不存在,格式不正确等情况)而被服务器拒绝执行,而不是命令实际执行时出错。
Redis的事务与传统的关系式数据库事务的最大区别在于,Redis不支持事务回滚机制(rollback),即使事务队列中的某个命令在执行期间出现了错误,整个事务也会继续执行下去,直到将事务队列中的所有命令都执行完毕为止。一定注意,Redis的事务性与常见的关系式数据库有些不同(尤其原子性),建议直接去看《Redis设计与实现》的19.3小节-事务的ACID性质,网上各种博客说的参差不齐。
5、当前Rediscluster集群有哪些方式,各自优缺点,场景。
Redis集群是Redis提供的分布式数据库方案,集群通过分片来进行数据共享,并提供复制和故障转移功能。
Redis集群使用数据分片(sharding)而非一致性哈希(consistencyhashing)来实现:一个Redis集群包含16384个哈希槽(hashslot),数据库中的每个键都属于这个16384个哈希槽的其中一个,集群使用公式CRC16(key)384来计算键key属于哪个槽,其中CRC16(key)语句用于计算键key的CRC16校验和。
?数据共享:Redis提供多个节点实例间的数据共享,也就是RedisA、B、C、D彼此之间的数据是同步的,同样彼此之间也可以通信,而对于客户端操作的keys是由Redis系统自行分配到各个节点中。
主从复制:Redis的多个实例间通信时,一旦其中一个节点故障,那么Redis集群就不能继续正常工作了,所以需要一种复制机制(Master-Slave)机制,做到一旦节点A故障了,那么其从节点A1和A2就可以接管并继续提供与A同样的工作服务。
哈希槽值:Redis集群中使用哈希槽来存储客户端的keys,而在Redis中,目前存有16384(2的14次方)个哈希槽,它们被全部分配给所有的节点。
??参考链接:Redis集群使用总结(一)
6、Memcache的原理,哪些数据适合放在缓存中。
Memcache采用键值对存储方式。它本质是一个大的hash表,key的最大长度为255个字符,最长过期时间为30天。它的内存模型如下:Memcache预先将可支配的内存空间进行分区(Slab),每个分区里再分为多个块(Chunk)最大1M,但同一个分区中块的大小是固定的。然后,插入数据时,会根据数据大小寻找最合适的块,然后插入,当然这样也就会有部分内存浪费,但可一定程度上减少内存碎片,总体上,利大于弊。
应用场景主要是分布式应用,数据库前段缓存和服务期间数据共享等。7、Redis相比memcached有哪些优势?两者的主要区别?
????memcached所有的值均是简单的字符串,Redis作为其替代者,支持更为丰富的数据类型
Redis的速度比memcached快很多Redis可以持久化其数据
Redis支持数据的备份,即master-slave模式的数据备份。
8、Redis的并发竞争问题如何解决,了解Redis事务的CAS操作吗?Redis的并发竞争问题主要是在并发写竞争上。体现在多客户端同时并发写一个key,修改值之后再写回去,只要顺序错了,数据就错了。
为了避免这个问题,我们可以对客户端读写Redis操作采用内部锁
synchronized。但解决这个问题最好的方案是Redis自己提供的CAS类的乐观锁方案。
redis具有高级事务CAS(乐观锁),可以被用作分布式锁。毕竟JVM提供的synchronized或者ReentrantLock不能应用于分布式环境下。
watch指令在redis事物中提供了CAS的行为。为了检测被watch的keys在是否有多个clients同时改变引起冲突,这些keys将会被监控。如果至少有一个被监控的key在执行exec命令前被其他客户端修改,整个事务将会回滚,不执行任何动作,从而保证原子性操作,并且执行exec会得到null的回复。具体工作机制:watch命令会监视给定的每一个key,当exec时如果监视的任一个key自从调用watch后发生过变化,则整个事务会回滚,不执行任何动作。注意watch的key是对整个连接有效的,事务也一样。如果连接断开,监视和事务都会被自动清除。
参考连接:redis的高级事务CAS(乐观锁)和Redis实现CAS的乐观锁9、Redis适合于哪些场景。
?????Session共享(单点登陆)页面缓存
队列(比如项目中用到的异步队列)排行榜/计数器
发布/订阅(实现消息流)
10、Redis持久化的机制,AOF和RDB的区别。
Redis提供两种方式进行持久化,一种是RDB持久化(会按照配置的指定时间将内存中的数据快照到磁盘中,创建一个dump.rdb文件,Redis启动时再恢复到内存中),另一种是AOF持久化(以日志的形式记录每个写操作(读操作不