java redis 面试题----持续补充

主文章(我总结的面试题的索引目录—进不去就说明我还没写完)
https://blog.csdn.net/grd_java/article/details/122357831

1. redis必问

简述下redis

  1. 作用于持久层的非关系型数据库,缓存型数据库,完全开源免费,遵守BSD协议,高性能key-value数据库
  2. 支持数据持久化,重启后可再次加载使用。还支持list、set、zset、hash等数据结构存储。支持数据备份(master-slave模式的数据备份)

redis的优势

  1. 性能极高:读的速度是110000次/s,写的次数是81000次/s
  2. 丰富的数据类型:支持二进制案例的Strings,Lists,Hashes,Sets,OrderedSets数据类型操作
  3. 原子性:Redis所有操作都是原子性(要么都成功,要不都失败)的,单个、多个操作都支持事务(原子性),通过MULTI和EXEC指令包起来
  4. 特性多样:支持publish/subscribe,通知,key过期等特性

使用Redis的好处,体现在哪?

  1. 速度快,数据在内存,数据结构使用散列表,此数据结构优势就是查找和操作的时间复杂度都是O(1)
  2. 丰富的数据类型,很多同类型产品,只有String一个类型,而reids支持string,list,set,Zset,hash。尤其hash数据类型,非常契合面向对象编程语言
  3. 支持事务,操作都是原子操作,对数据的修改要么全部执行,要么全部不执行(中间出错,全体回滚)
  4. 特性多,可用于缓存,消息,设置key的过期时间(过期自动删除)

2. 5种数据类型和应用场景

redis的应用场景

  1. redis有5大value类型,不同类型有不同应用场景
  2. 基本上都是当缓存用,也有用来做session共享,消息订阅发布的这种
  3. 主要目的是服务无状态,比如项目中某些数据结构或对象,单机时需要单机锁,分布式时需要分布式锁,抽出来放在redis中。
  1. 比如,两个微服务互相调用,A服务调用B服务,A先修改了数据库,调用了B,B又修改了数据库。此时A发生错误,A回滚。但是B是不知道的,B和A不在一个事务,无法回滚
  2. 所以可以借助redis,进行分布式事务。
  1. 现在主流大厂偏向于"无锁化",尽量不用锁,速度就快

redis有几种数据类型,分别是什么?

  1. redis的键值对中,value的值有5种数据类型,key统一都是string字符串类型
  2. 5种数据类型分别是:string字符串、hash哈希、list列表、set集合、zset(sorted set)有序集合
  1. string类型:最基本类型,最大存储512M,如果里面存储的是数字值,那么可以通过incr key(key表示键)和decr key两个命令,对其进行增加和减少操作,可用于保存高热量数据值,比如点击量,用户只有点击,就调用incr key命令让里面的值加1.
  2. hash类型:就是一个hashMap,一般我们通过JSON字符串保存对象,而解析时,需要反序列化。使用hash类型,就省去了这个麻烦,它可以直接让我们访问到对象的特定某一条属性。注意,hash类型的键值对表现形式是field—value
    在这里插入图片描述
  1. list类型:简单的字符串列表,按插入顺序排序,可以添加元素到头(左)或尾(右),最多2^32-1个元素(42949672295,一个列表超过40亿个),底层使用压缩列表和双向链表数据结构,压缩列表达到一定条件转换为双向链表。适用于字符串按先后顺序展示的场景,比如朋友圈点赞,按顺序显示谁先点赞
  2. set类型:不可重复的字符串列表,无序,和Java一样,通过hash表实现,添加删除查找,时间复杂度都是O(1),最多2^32-1个元素(42949672295,一个set超过40亿个),常用于屏蔽菜单,比如屏蔽的弹幕关键字,你又不会关注它的顺序
  3. zset类型:有序或者说会自动排序的set类型。他和java不一样,java的有序,是插入顺序,redis这个实实在在的实现了排序。它在set基础上,为每个元素,关联了double类型的分数score,redis通过此分数为集合中成员进行从小到大的排序。集合元素不可重复,但是分数score可以重复,如果插入重复元素,后插入的元素的score覆盖之前的元素的score,score可以指定。适用于排行榜。
  4. 其它的高级数据结构:HyperLogLog、Geo、Pub/Sub、Redis Module、BloomFilter、RedisFilter、RedisSearch、Redis-ML。真的会再说,不会就不要提。

3. 同类型产品优势

Redis和Memcached相比有哪些优势?

  1. Memcached所有值都是简单字符串,redis作为它的替代,支持丰富数据类型
  2. redis速度比Memcached快很多
  3. Redis可以持久化数据

Memcache与Redis的区别

  1. 存储方式不同:Memcache把数据全部放在内存,断点就会丢失,数据不能超过内存大小,Redis可以持久化数据到硬盘,保证数据持久性
  2. 数据类型:Memcache对数据类型支持简单,Redis有复杂的数据类型
  3. 底层模型不同:底层实现方式、与客户端间通信协议不一样。Redis自己构建VM机制,一般系统调用系统函数的话,会浪费一定时间去移动和请求,而Redis自己有VM机制,自己去请求。

4. 细节

redis是单线程还是多线程?

  1. 无论什么版本,工作线程只有一个, redis利用队列技术,将并发访问变成串行访问,消除了传统数据库串行控制的开销
  2. 6.x高版本出现了IO多线程,数据计算依然是单线程
  3. 为什么IO多线程了呢?因为这是IO模型编程的知识,redis调用系统内核,将数据搬运到程序中(第一步,也就是IO)。搬运回来之后,才会进行数据处理(第二步,也就是工作线程),过时超时等操作。

6.x以前redis的底层工作方式是怎么样的?

  1. 6.x以前,redis工作线程只有一条,无论是否有多个客户端同时建立连接,他们都会先和redis的内核中的epoll打交道,挂载自己的事件到epoll,比如读事件
  2. 简单介绍一下epoll
  1. 一个内存模型,一个多路复用器,和Java NIO的select一样,select也是一个内存模型,Java就是通过面向IO模型编程,封装成了Selector选择器
  2. 和select一样,它不负责数据读写,只是管理读写事件,主要是为了非阻塞式IO,我看你到底发不发数据,如果你要读,我管理你的读事件,要写我管理你的写事件,如果你不读不写,那我不会管你。阻塞式IO,会阻塞住等着它。
  1. redis工作线程,先去epoll中看有没有事件,比如发现了刚才的读事件,他就会和redis内核读取数据,读取完成后,再进行计算(根据你的指令进行相应计算),最后返回(输出)计算完成的数据
  2. 工作线程的这些操作都是在一个管道中执行的,就是一个队列,一个执行完了,再执行另一个。比如客户端A的执行完,执行客户端B的。这样就让并发访问,变成了串行。
  3. redis的单指令操作是原子的,就是pipeline一个客户端的指令集合。也就是说,客户端会攒一堆指令,组成pipeline一次性发过来。原子性表示要么全成功,要么全失败。
  4. 如果使用事务,就不是攒成一个pipeline,而是服务端攒(把指令积攒到服务端队列里),所以事务的执行期是原子的。那么问题来了,如果发了3条指令,有一条失败了,事务回滚吗?答案是不回滚,失败就是失败了,其它指令继续执行。和mysql不一样
  5. 所以注意使用逻辑,少使用事务。如果一定要用,因为指令会积攒到服务端队列,一定要保证客户端事务期间的指令,少和快。

6.x以后redis底层工作方式是怎么样的(下面这里我就说出与6.x以前的不同,其它都一样)?

  1. 工作线程依然只有一条,但是多了IO线程,工作线程不在管IO的事了。IO线程可以有多个,比如每个客户端一个工作线程。
  2. 当redis在epoll中监听到多个客户端,就通知IO线程,并行的去内核,将数据搬运回来。而以前版本,搬运也是串行的,一个一个搬。
  3. 然后搬运完,数据交给工作线程计算,计算完成后,给IO线程,返回结果
  4. 适用于服务器是多核cpu的情况下,充分压榨cpu资源。
  5. 一句话总结就是,6.x以前,活全由工作线程干,处理客户端A的指令,先读取数据,再计算,最后再把结果返回。然后处理客户端B的。这样的串行执行。6.x以后,IO线程并发读数据,然后串行放在redis队列,计算,最后结果由IO线程并行输出。也就是多个客户端的输入和输出,放到了其它线程去并行执行。
    在这里插入图片描述

多个客户端连接,如果保障处理顺序?

  1. 多个客户端连接,是A先还是B先执行,无法得到保障
  2. 但是同一个socket连接里面的执行顺序可以保证,比如先获取数据,然后再处理,然后再输出数据。
  3. 建立一个socket连接,就会建立一个通道,在通道中按顺序走,所以可以保证处理顺序。
  4. 也就是通道与通道,连接与连接之间,运行可能是交叉的,但是一个通道中的操作一定是有序的。

redis一个string类型的值,能存储最大容量是多少

512M

redis存在线程安全吗?为什么?

  1. 存在,redis是单线程串行,可以保证内部串行,多个客户端同时访问,依然串行执行,但是谁先谁后没法保证。
  2. 所以外部使用的时候,业务上要自行保障顺序。
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

殷丿grd_志鹏

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值