简介
Redis 是一个开源的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。 它支持多种类型的数据结构,如 字符串(strings), 散列(hashes), 列表(lists), 集合(sets), 有序集合(sorted sets) 与范围查询, bitmaps, hyperloglogs 和 地理空间(geospatial) 索引半径查询等。 Redis 内置了 复制(replication),LUA脚本(Lua scripting), LRU驱动事件(LRU eviction),事务(transactions) 和不同级别的 磁盘持久化(persistence), 并通过 Redis哨兵(Sentinel)和自动 分区(Cluster)提供高可用性(high availability)。
为什么使用缓存服务器
缓存是高并发场景下提高热点数据访问性能的一个有效手段,在开发项目时会经常使用到。
缓存的类型分为:本地缓存、分布式缓存和多级缓存。
本地缓存 就是在进程的内存中进行缓存,比如我们的 JVM 堆中,本地缓存是内存访问,没有远程交互开销,性能最好,但是受限于单机容量,一般缓存较小且无法扩展。
分布式缓存一般都具有良好的水平扩展能力,对较大数据量的场景也能应付自如。缺点就是需要进行远程请求,性能不如本地缓存。
为了平衡这种情况,实际业务中一般采用多级缓存,本地缓存只保存访问频率最高的部分热点数据,其他的热点数据放在分布式缓存中。
Redis & Memcached
-
数据结构:Memcached只支持简单的key/value数据结构,不像Redis可以支持丰富的数据类型。
-
持久化:Memcached无法进行持久化,数据不能备份,只能用于缓存使用,且重启后数据全部丢失。
-
多线程:Redis 使用单线程反而避免了多线程的频繁上下文切换问题,预防了多线程可能产生的竞争问题。
Memcache 存在着支持并发性不好、可运维性欠佳、原子性操作不够、在误操作时产生数据不一致等问题。
由于 Redis 只使用单核,而 Memcached 可以使用多核,所以 Redis 在存储小数据时比 Memcached 性能更高。而在 100k 以上的数据中,Memcached 性能要高于 Redis,虽然 Redis 最近也在存储大数据的性能上进行优化,但是比起 Memcached,还是稍有逊色。
-
分布式:Redis原生支持集群模式,Memcached没有原生的集群模式。
Redis 支持通过Replication进行数据复制,通过master-slave机制,可以实时进行数据的同步复制,支持多级复制和增量复制,master-slave机制是Redis进行HA的重要手段。
线程模型
Redis 内部使用文件事件处理器 file event handler
,这个文件事件处理器是单线程的,所以 Redis 才叫做单线程的模型。它采用 IO 多路复用机制同时监听多个 Socket,根据 Socket 上的事件来选择对应的事件处理器进行处理。
文件事件处理器的结构包含 4 个部分:
- 多个 Socket
- IO 多路复用程序
- 文件事件分派器
- 事件处理器(连接应答处理器、命令请求处理器、命令回复处理器)
多个 Socket 可能会并发产生不同的操作,每个操作对应不同的文件事件,但是 IO 多路复用程序会监听多个 Socket,会将 Socket 产生的事件放入队列中排队,事件分派器每次从队列中取出一个事件,把该事件交给对应的事件处理器进行处理。
为什么Redis单线程也能效率这么高?
- 完全基于内存,绝大部分请求是纯粹的内存操作,非常快速。它的数据存在内存中,类似于HashMap,HashMap 的优势就是查找和操作的时间复杂度都是O(1);
- 采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗;
- 使用多路I/O复用模型,非阻塞IO;
- Redis 直接自己构建了 VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求;
数据结构
基本:String、Hash、List、Set、SortedSet
进阶:HyperLogLog、Geo、Pub/Sub、bitmaps
高级:BloomFilter
基本
String:存储简单的对象序列化字符串,应用场景:缓存热点数据、计数器、会话token
Hash:保存无嵌套的对象属性
List:列表,应用场景:简单消息队列、分页
Set:无序集合,自动去重,应用场景:共同好友
Sorted Set:有序集合,自动去重,应用场景:排行榜、微博热搜
进阶
Geo:可以用来保存地理位置,并作位置距离计算或者根据半径计算位置等。 应用场景:附近的人
Pub/Sub:订阅/发布,应用场景:简单消息队列
HyperLogLog:用来做基数统计的算法 ,比如数据集 {1, 3, 5, 7, 5, 7, 8}, 那么这个数据集的基数集为 {1, 3, 5 ,7,