一、基础总结篇
1、谈一下 Redis 的优缺点
优点:
-
读写性能优异, Redis能读的速度是
110000
次/s,写的速度是81000
次/s -
支持数据持久化,支持 AOF 和 RDB 两种持久化方式
-
支持事务,Redis 的所有操作都是原子性的
-
数据结构丰富,除了支持 string 类型的 value 外,还支持 list、hash、set、zset 等数据结构
-
支持主从复制,主机会自动将数据同步到从机,可以进行读写分离
缺点:
-
容量受物理内存的限制,不能用作海量数据的高性能读写,因此 Redis 适合的场景主要局限在较小数据量的高性能操作和运算上。
-
不具备自动容错和恢复,主机从机的宕机都会导致前端部分读写请求失败,需要等待机器重启或者手动切换前端的 IP 才能恢复。
-
系统可用性不是很高,主机宕机,宕机前有部分数据未能及时同步到从机,切换 IP 后还会引入数据不一致的问题,降低了系统的可用性
-
Redis 较难支持在线扩容,在集群容量达到上限时在线扩容会变得很复杂。为避免这一问题,运维人员在系统上线时必须确保有足够的空间,这对资源造成了很大的浪费。
2、你们为什么使用 Redis
当前线上应用现状
在日常的 Web 应用对数据库的访问中,读操作的次数远超写操作,比例大概在 1:9 到 3:7,所以需要读的可能性是比写的可能大得多的。当我们使用 SQL 语句去数据库进行读写操作时,数据库就会 去磁盘把对应的数据索引取回来,这是一个相对较慢的过程。
使用缓存(Redis)带来的优势
如果我们把数据放在 Redis 中,也就是直接放在内存之中,让服务端直接去读取内存中的数据,那么这样 速度 明显就会快上不少,提升系统的性能 (高性能),并且特别是在高并发的场景下会 极大减小数据库的压力 。
3、使用缓存中常见问题
什么是缓存雪崩、缓存穿透 和 缓存击穿,对应的解决方案是什么?
参考我的另一篇博客:redis-12 缓存雪崩、穿透和击穿详解
实际中缓存和数据库双写一致性问题如何解决?
参考我的另一篇博客:redis-14 缓存和数据库双写一致性问题详解
4、Redis 早期版本为什么选择单线程
官方解释
因为 Redis 是基于内存的操作,CPU 不是 Redis 的瓶颈,Redis 的瓶颈最有可能是 机器内存的大小 或者 网络带宽。既然单线程容易实现,而且 CPU 不会成为瓶颈,那就顺理成章地采用单线程的方案了。
自我总结
-
使用单线程模型能带来更好的 可维护性,方便开发和调试;
-
使用单线程模型也能 并发 的处理客户端的请求;(I/O 多路复用机制)
-
Redis 服务中运行的绝大多数操作的 性能瓶颈都不是 CPU
5、Redis 既然是单线程为什么还这么快
-
纯内存操作:读取不需要进行磁盘 I/O,所以比传统数据库要快上不少;(但不要有误区说磁盘就一定慢,例如 Kafka 就是使用磁盘顺序读取但仍然较快)
-
单线程,无锁竞争:这保证了没有线程的上下文切换,不会因为多线程的一些操作而降低性能;
-
多路 I/O 复用模型+消息回调,非阻塞 I/O:采用多路 I/O 复用技术可以让单个线程高效的处理多个网络连接请求(尽量减少网络 IO 的时间消耗),例如使用了 epoll 且消息回调机制,充分的降低了用户态 和 内核态的耗时,详情可参考我的另外一篇博客:redis-10 redis和 I/O多路复用;
-
高效的数据结构,加上底层做了大量优化:Redis 对于底层的数据结构和内存占用做了大量的优化,例如不同长度的字符串使用不同的结构体表示等等..;详情可参考我的另外一篇博客:redis-02 五种类型底层数据结构
第二、数据结构篇
6、Redis 的 SDS 和 C 中字符串相比优势是什么
C 语言使用了一个长度为 N+1
的字符数组来表示长度为 N
的字符串,并且字符数组最后一个元素总是