Redis — 工具 与其他
📋 本文节选自《Redis 面试题》,返回 查看全部章节
八、常用工具
57. Redis支持的Java客户端都有哪些?官方推荐用哪个?
- Redisson、Jedis、lettuce等等,官方推荐使用Redisson。
58. Redis和Redisson有什么关系?
- Redisson是一个高级的分布式协调Redis客服端,能帮助用户在分布式环境中轻松实现一些Java的对象 (Bloom filter, BitSet, Set, SetMultimap, ScoredSortedSet, SortedSet, Map,ConcurrentMap, List, ListMultimap, Queue, BlockingQueue, Deque, BlockingDeque,Semaphore, Lock, ReadWriteLock, AtomicLong, CountDownLatch, Publish / Subscribe,HyperLogLog)。
59. Jedis与Redisson对比有什么优缺点?
- Jedis是Redis的Java实现的客户端,其API提供了比较全面的Redis命令的支持;Redisson实现了分布式和可扩展的Java数据结构,和Jedis相比,功能较为简单,不支持字符串操作,不支持排序、事务、管道、分区等Redis特性。Redisson的宗旨是促进使用者对Redis的关注分离,从而让使用者能够将精力更集中地放在处理业务逻辑上。
九、其他问题
60. Redis与Memcached的区别
- 两者都是非关系型内存键值数据库,现在公司一般都是用 Redis 来实现缓存,而且 Redis 自身也越来越强大了!Redis 与 Memcached 主要有以下不同:
| 对比参数 | Redis | Memcached |
|---|---|---|
| 类型 | 1. 支持内存 2. 非关系型数据库 | 1. 支持内存 2. 键值对形式 3. 缓存形式 |
| 数据存储类型 | 1. String 2. List 3.Set 4. Hash 5.Sort Set 【俗称ZSet】 | 1. 文本型 2. 二进制类型 |
| 查询【操作】类型 | 1. 批量操作 2. 事务支持 3. 每个类型不同的CRUD | 1.常用的CRUD 2. 少量的其他命令 |
| 附加功能 | 1. 发布/订阅模式2. 主从分区 3. 序列化支持 4. 脚本支持【Lua脚本】 | 1. 多线程服务支持 |
| 网络IO模型 | 1. 单线程的多路IO 复用模型 | 1. 多线程,非阻塞IO模式 |
| 事件库 | 自封转简易事件库AeEvent | 贵族血统的LibEvent事件库 |
| 持久化支持 | 1. RDB 2. AOF | 不支持 |
| 集群模式 | 原生支持 cluster模式,可以实现主从复制,读写分离 | 没有原生的集群模式,需要依靠客户端来实现往集群中分片写入数据 |
| 内存管理机制 | 在 Redis 中,并不是所有数据都一直存储在内存中,可以将一些很久没用的 value 交换到磁盘 | Memcached 的数据则会一直在内存中,Memcached 将内存分割成特定长度的块来存储数据,以完全解决内存碎片的问题。但是这种方式会使得内存的利用率不高,例如块的大小为 128 bytes,只存储 100 bytes 的数据,那么剩下的28 bytes就浪费掉了。 |
| 适用场景 | 复杂数据结构,有持久化,高可用需求,value存储内容较大 | 纯key-value,数据量非常大,并发量非常大的业务 |
1、 memcached所有的值均是简单的字符串,redis作为其替代者,支持更为丰富的数据类型;
2、 redis的速度比memcached快很多;
3、 redis可以持久化其数据;
61. 如何保证缓存与数据库双写时的数据一致性?
- 你只要用缓存,就可能会涉及到缓存与数据库双存储双写,你只要是双写,就一定会有数据一致性的问题,那么你如何解决一致性问题?
- 一般来说,就是如果你的系统不是严格要求缓存+数据库必须一致性的话,缓存可以稍微的跟数据库偶尔有不一致的情况,最好不要做这个方案,读请求和写请求串行化,串到一个内存队列里去,这样就可以保证一定不会出现不一致的情况
- 串行化之后,就会导致系统的吞吐量会大幅度的降低,用比正常情况下多几倍的机器去支撑线上的一个请求。
- 还有一种方式就是可能会暂时产生不一致的情况,但是发生的几率特别小,就是先更新数据库,然后再删除缓存。
| 问题场景 | 描述 | 解决 |
|---|---|---|
| 先写缓存,再写数据库,缓存写成功,数据库写失败 | 缓存写成功,但写数据库失败或者响应延迟,则下次读取(并发读)缓存时,就出现脏读 | 这个写缓存的方式,本身就是错误的,需要改为先写数据库,把旧缓存置为失效;读取数据的时候,如果缓存不存在,则读取数据库再写缓存 |
| 先写数据库,再写缓存,数据库写成功,缓存写失败 | 写数据库成功,但写缓存失败,则下次读取(并发读)缓存时,则读不到数据 | 缓存使用时,假如读缓存失败,先读数据库,再回写缓存的方式实现 |
| 需要缓存异步刷新 | 指数据库操作和写缓存不在一个操作步骤中,比如在分布式场景下,无法做到同时写缓存或需要异步刷新(补救措施)时候 | 确定哪些数据适合此类场景,根据经验值确定合理的数据不一致时间,用户数据刷新的时间间隔 |
62. Redis常见性能问题和解决方案?
1、 Master最好不要做任何持久化工作,包括内存快照和AOF日志文件,特别是不要启用内存快照做;持久化。
2、 如果数据比较关键,某个Slave开启AOF备份数据,策略为每秒同步一次;
3、 为了主从复制的速度和连接的稳定性,Slave和Master最好在同一个局域网内;
4、 尽量避免在压力较大的主库上增加从库;
5、 Master调用BGREWRITEAOF重写AOF文件,AOF在重写的时候会占大量的CPU和内存资源,导致;服务load过高,出现短暂服务暂停现象。
6、 为了Master的稳定性,主从复制不要用图状结构,用单向链表结构更稳定,即主从关系为:;Master<–Slave1<–Slave2<–Slave3…,这样的结构也方便解决单点故障问题,实现Slave对Master的替换,也即,如果Master挂了,可以立马启用Slave1做Master,其他不变。
63. Redis官方为什么不提供Windows版本?
- 因为目前Linux版本已经相当稳定,而且用户量很大,无需开发windows版本,反而会带来兼容性等问题。
64. 一个字符串类型的值能存储最大容量是多少?
- 512M
65. Redis如何做大量数据插入?
- Redis2.6开始redis-cli支持一种新的被称之为pipe mode的新模式用于执行大量数据插入工作。
66. 假如Redis里面有1亿个key,其中有10w个key是以某个固定的已知的前缀开头的,如果将它们全部找出来?
- 使用keys指令可以扫出指定模式的key列表。
- 对方接着追问:如果这个redis正在给线上的业务提供服务,那使用keys指令会有什么问题?这个时候你要回答redis关键的一个特性:redis的单线程的。keys指令会导致线程阻塞一段时间,线上服务会停顿,直到指令执行完毕,服务才能恢复。这个时候可以使用scan指令,scan指令可以无阻塞的提取出指定模式的key列表,但是会有一定的重复概率,在客户端做一次去重就可以了,但是整体所花费的时间会比直接用keys指令长。
67. 使用Redis做过异步队列吗,是如何实现的
- 使用list类型保存数据信息,rpush生产消息,lpop消费消息,当lpop没有消息时,可以sleep一段时间,然后再检查有没有信息,如果不想sleep的话,可以使用blpop, 在没有信息的时候,会一直阻塞,直到信息的到来。redis可以通过pub/sub主题订阅模式实现一个生产者,多个消费者,当然也存在一定的缺点,当消费者下线时,生产的消息会丢失。
68. Redis如何实现延时队列
- 使用sortedset,使用时间戳做score, 消息内容作为key,调用zadd来生产消息,消费者使用zrangbyscore获取n秒之前的数据做轮询处理。
69. Redis回收进程如何工作的?
1、 一个客户端运行了新的命令,添加了新的数据;
2、 Redis检查内存使用情况,如果大于maxmemory的限制,则根据设定好的策略进行回收;
3、 一个新的命令被执行,等等;
4、 所以我们不断地穿越内存限制的边界,通过不断达到边界然后不断地回收回到边界以下;
如果一个命令的结果导致大量内存被使用(例如很大的集合的交集保存到一个新的键),不用多久内存限制就会被这个内存使用量超越。
70. Redis回收使用的是什么算法?
- LRU算法
为了帮助更多的粉丝朋友,找到个好工作,多拿几个offer。苏三最近建一些工作内推群,群里目前已经收集了很多内推岗位,大厂、中厂、小厂、外包都有。欢迎HR、开发、测试、运维和产品加入。

扫描下方微信,备注:网站+所在城市,即可拉你进工作内推群。
