1,概述,总结什么是redis?
Redis是一个使用 C 语言编写的,开源的高性能非关系型(NoSQL)的键值对数据库。
Redis 可以存储键和五种不同类型的值之间的映射。键的类型只能为字符串,值支持五种数据类型:字符串、列表、集合、散列表、有序集合。
与传统数据库不同的是 Redis 的数据是存在内存中的,所以读写速度非常快,因此 redis 被广泛应用于缓存方向,每秒可以处理超过 10万次读写操作,是已知性能最快的Key-Value DB。另外,Redis 也经常用来做分布式锁。
除此之外,Redis 支持事务 、持久化、LUA脚本、LRU驱动事件、多种集群方案。Redis的持久化可以将数据写入磁盘中,保证了数据的安全不丢失,而且Redis的操作是原子性的。
2,Redis有哪些优缺点?
优点:
- 基于内存操作,读写性能优异, Redis能读的速度是110000次/s,写的速度是81000次/s。
- 支持数据持久化,支持AOF和RDB两种持久化方式,可以有效地避免数据丢失问题。
- 支持事务,Redis的所有操作都是原子性的,同时Redis还支持对几个操作合并后的原子性执行。
- 数据结构丰富,除了支持string类型的value外还支持hash、set、zset、list等数据结构。
- 支持主从复制,主机会自动将数据同步到从机,可以进行读写分离。
缺点:
- 数据库容量受到物理内存的限制,不能用作海量数据的高性能读写,因此Redis适合的场景主要局限在较小数据量的高性能操作和运算上。
- Redis 不具备自动容错和恢复功能,主机从机的宕机都会导致前端部分读写请求失败,需要等待机器重启或者手动切换前端的IP才能恢复。
主机宕机,宕机前有部分数据未能及时同步到从机,切换IP后还会引入数据不一致的问题,降低了系统的可用性。 - Redis较难支持在线扩容,在集群容量达到上限时在线扩容会变得很复杂。为避免这一问题,运维人员在系统上线时必须确保有足够的空间,这对资源造成了很大的浪费。
3,Redis为什么这么快
基于内存:Redis是使用内存存储,没有磁盘IO上的开销。数据存在内存中,读写速度快。
单线程实现( Redis 6.0以前):Redis使用单个线程处理请求,避免了多个线程之间线程切换和锁资源争用的开销。
IO多路复用模型:Redis 采用 IO 多路复用技术。Redis 使用单线程来轮询描述符,将数据库的操作都转换成了事件,不在网络I/O上浪费过多的时间。
高效的数据结构:Redis 每种数据类型底层都做了优化,数据结构简单,对数据操作也简单,目的就是为了追求更快的速度。
4,Redis为何选择单线程
Redis操作基于内存,绝大多数操作的性能瓶颈不在CPU
- 避免过多的上下文切换开销。程序始终运行在进程中单个线程内,没有多线程切换的场景。
- 避免同步机制的开销:如果 Redis选择多线程模型,需要考虑数据同步和加锁的问题,则必然会引入某些同步机制,会导致在操作数据过程中带来更多的开销,增加程序复杂度的同时还会降低性能。
- 实现简单,方便维护:如果 Redis使用多线程模式,那么所有的底层数据结构的设计都必须考虑线程安全问题,那么 Redis 的实现将会变得更加复杂。
5,Redis6.0为何引入多线程?
Redis6 版本中引入了多线程。之前已经提到过 Redis 单线程处理有着很快的速度,那为什么还要引入多线程呢?单线程的瓶颈在什么地方?
先来看第二个问题,在 Redis 中,单线程的性能瓶颈主要在网络IO操作上。也就是在读写网络的read/write系统调用执行期间会占用大部分CPU时间。如果要对一些大的键值对进行删除操作的话,在短时间内是删不完的,那么对于单线程来说就会阻塞后边的操作。
Redis6.0的多线程是指,将网络数据读写和协议解析通过多线程的方式来处理,对于命令执行来说,仍然使用单线程操作。也就是说,Redis6.0的多线程是为了解决其网络IO的瓶颈。