一、Redis缓存的特点
作为一个高性能的 Key-Value 数据库,Redis 与其他 Key-Value 缓存产品相比,有以下三个特点:
- Redis 运行在内存中但是可以 持久化到磁盘,重启的时候可以再次加载进行使用。
- Redis 不仅仅支持简单的 Key-Value 类型的数据,同时还提供 List,Set,Sorted set,hash 等数据结构的存储。
- Redis 还支持数据的备份,即 Master-Slave 主从模式的数据备份。
二、Redis 和 MySQL 的区别
- 首先,类型上的不同。MySQL 是关系型数据库,采用表格的存储方式,数据以行列组织:一个表中,每行是一个条目,都有且仅有此表的列所规定的属性。MySQL 作为关系型数据库遵守了传统的数据库的 ACID 原则 [①],这些要求在记录重要数据(如用户账户密码,银行户头等)时是必须的。Redis 是 NoSQL(非关系型数据库),不严格遵守 ACID 原则,其采用 key-value 存储组织数据,大量使用缓存来读写数据,周期性地把更新数据写入磁盘或在追加文件中写入修改操作,以及同步分布数据库等。这些特点为大大提高了 Redis 在极大并发量下的读写性能。由于不以表格方式组织数据,Redis 的数据扩展十分灵活方便。
- 功能不同。 MySQL 主要用于持久化的存储数据到硬盘,功能强大,但是读取速度较慢。而 Redis 将使用频繁的数据存储在缓存中,缓存的读取速度快,能够大大的提高运行效率,但是一般在使用中,Redis 缓存的数据保存时间是有限的。
- 运行机制不同。MySQL 作为典型的关系型数据库,为了严格遵守 ACID 规则必须采取保守的缓存策略,特别是为了保证数据的一致性,在保证数据可靠性的同时,牺牲了许多(特别是多并发情形下的)读写性能。而现在互联网许多应用场景往往面临了海量用户的访问请求,对数据库并不需要非常强的一致性 [②]。如 Redis 等非关系型数据库(NoSQL),往往以不再满足 ACID 为代价求得更高的吞吐容量。NoSQL 通常采用极大的缓存、分布式服务来提高读写性能。
① 原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。
② 比如推特网站的用户在当次刷新推特时,容许在最新 10 秒内新发的推特不出现在这次刷新结果,但是不希望自己的应用因为等待刷新而陷入 5 秒以上的停顿。
三、Redis 和 MongoDB 的区别
MongoDB 和 Redis 都是 NoSQL,采用结构型数据存储,二者之间的主要区别如下所示:
- 性能方面,二者都很高,总体而言,TPS 方面 Redis 要大于 MongoDB;
- 可操作性上,MongoDB 支持丰富的数据表达、索引,最类似于关系数据库,支持 丰富的查询语言,操作比 Redis 更为便利;
- 内存及存储方面,MongoDB 适合 大数据量存储,依赖操作系统虚拟做内存管理,采用镜像文件存储,内存占有率比较高,Redis 2.0 后增加 虚拟内存特性,突破物理内存限制,数据可以设置时效性;
- 对于数据持久化和数据恢复,MongoDB 1.8 后,采用 binlog 方式(同 MySQL)支持持久化,增加了可靠性,而 Redis 依赖快照进行持久化、AOF 增强可靠性,但是增强可靠性的同时,也会影响访问性能;
- 在数据一致性上,MongoDB 不支持事务,靠客户端自身保证,而 Redis 支持事务,能保证事务中的操作按顺序执行;
- 数据分析上,MongoDB 内置 数据分析功能(mapreduce),而 Redis 不支持数据分析;
- 应用场景不同,MongoDB 适合海量数据,侧重于访问效率的提升,而 Redis 适合于较小数据量,侧重于性能。
四、Redis 有哪些数据类型
Redis 的五大常用数据类型:
- String(字符串),是 Redis 最基本的数据类型,二进制安全的,可以包含任何数据,比如 JPG 图片或者序列化的对象,最大能存储 512 MB。
- Hash(哈希),是一个键值对(key => value)集合,特别适合用于存储对象。
- List(列表),Redis 列表是简单的字符串列表,按照插入顺序排序,可以添加一个元素到列表的头部(左边)或者尾部(右边)。
- Set(集合),是 String 类型的无序集合,通过哈希表实现,添删查找操作的复杂度都是 O(1)。
- Sorted set(有序集合),和 Set 一样也是 String 类型元素的集合,且不允许元素重复, 不同的是每个元素都会关联一个 Double 类型的分数(可重复), 通过此分数来为集合中的成员进行从小到大的排序。
五、如何实现 Redis 的定时机制
Redis 服务器是一个 事件驱动程序,服务器需要处理以下两类事件:文件事件 (服务器对套接字操作的抽象)和 时间事件(服务器对定时操作的抽象)。Redis 的定时机制就是借助时间事件实现的。
一个时间事件主要由以下三个属性组成:id,时间事件标识号;when,记录时间事件的到达时间;timeProc,时间事件处理器,当时间事件到达时,服务器就会调用相应的处理器来处理时间。一个时间事件根据时间事件处理器的返回值来判断是定时事件还是周期性事件。
六、单线程 Redis,为什么如此高效
虽然 Redis 文件事件处理器以单线程方式运行,但是通过使用 I/O 多路复用程序 来监听多个套接字,文件事件处理器既实现了高性能的网络通信模型,又可以很好地与 Redis 服务器中其他同样以单线程运行的模块进行对接,这保持了 Redis 内部单线程设计的简单性。
七、Redis 有哪些数据淘汰策略
Redis 内存数据量达到一定限制的时候,就会实行数据淘汰策略(回收策略)。Redis 会根据 maxmemory-policy 配置策略,来决定具体的行为:
- no-eviction:不删除策略,达到最大内存限制时刻,如果需要更多内存,直接返回错误信息;
- allkey-lru:从所有 Key 的哈希表(server.db[i].dict)中随机挑选多个 Key,然后在选到的 Key 中利用 lru 算法淘汰最近最少使用的数据;
- volatile-lru:从已设置过期时间的哈希表(server.db[i].expires)中随机挑选多个 Key,然后在选到的 Key 中用 lru 算法淘汰最近最少使用的数据;
- volatile-random:从已设置过期时间的哈希表(server.db[i].expires)中随机挑选 Key淘汰掉;
- allkey-random:从所有的 Key 的哈希表(server.db[i].dict)中随机挑选数据淘汰;
- volatile-ttl:从已设置过期时间的哈希表(server.db[i].expires)中随机挑选多个 Key,然后在选到的 Key 中选择剩余时间最短的数据淘汰掉。
八、对 Redis 的理解
Redis,全称为 Remote Dictionary Server,本质上是一个 Key-Value 类型的内存数据库,整个数据库统统加载在内存当中进行操作,定期通过异步操作把数据库数据写入磁盘或把修改操作写入追加的记录文件,并且在此基础上实现 Master-Slave(主从)同步。它支持存储的 Value 类型多样,包括 String(字符串)、List(链表)、Set(集合)、zset(sorted set —— 有序集合)和 Hash(哈希类型),这些数据类型都支持 push/pop、add/remove 及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。
Redis 的主要缺点是数据库容量受到物理内存的限制,不能用作海量数据的高性能读写,因此 Redis 适合的场景主要局限在较小数据量的高性能操作和运算上。