1.概述
Redis 是速度非常快的非关系型(NoSQL)内存键值数据库,可以存储键和五种不同类型的值之间的映射。
键(key)的类型只能为字符串(String),
值(value) 支持五种数据类型:字符串(String)、列表(list)、集合(set)、有序集合(zset)、哈希(hash)。
Redis 支持很多特性,例如将内存中的数据持久化到硬盘中,使用复制来扩展读性能,使用分片来扩展写性能。
Redis的使用场景
(1)缓存:Redis当今最为人熟知的使用场景。再提升服务器性能方面非常有效;
(2)排行榜:利用Redis的 Zset数据结构能够非常方便搞定;[Zset]
(3)计算器/限速器:利用Redis中原子性的自增操作,我们可以统计类似用户点赞数、用户访问数等,这类操作如果用MySQL,频繁的读写会带来相当大的压力;限速器比较典型的使用场景是限制某个用户访问某个API的频率,常用的有抢购时,防止用户疯狂点击带来不必要的压力;
注:限速器也是对请求限流的一种实现方式。[String](4)好友关系:利用集合的一些命令,比如求交集、并集、差集等。可以方便搞定一些共同好友、共同爱好之类的功能;[Set]
(5)简单消息队列:除了Redis自身的发布/订阅模式,我们也可以利用List来实现一个队列机制,比如:到货通知、邮件发送之类的需求,不需要高可靠,但是会带来非常大的DB压力,完全可以用List来完成异步解耦;不过最好用kafka、RabbitMQ等消息中间件。[List]
(6)Session共享:默认Session是保存在服务器的文件中,即当前服务器,如果是集群服务,同一个用户过来可能落在不同机器上,这就会导致用户频繁登陆;采用Redis保存Session后,无论用户落在那台机器上都能够获取到对应的Session信息。[Set]
Redis优点:
- 速度快,完全基于内存;(Redis将数据存储在内存上,避免了频繁的IO操作 )
- 使用C语言实现,网络层使用epoll解决高并发问题;
- 单线程模型避免了不必要的上下文切换及竞争条件;(Redis是单线程的,避免了上下文切换带来的消耗,采用网络IO多路复用技术来保证在多连接的时候, 系统的高吞吐量。)
- Redis其本身采用字典的数据结构,时间复杂度为O(1),且其采用渐进式的扩容手段 .Redis全程使用hash结构,读取速度快,还有一些特殊的数据结构,对数据存储进行了优化,如压缩表,对短数据进行压缩存储,再如,跳跃表,使用有序的数据结构加快读取的速度。
Redis的缺点:
滥用可能导致系统的不稳定、成本增高等问题。
- 比如,用Redis去保存用户的基本信息,虽然它能够支持持久化,但是它的持久化方案并不能保证数据绝对的落地,并且还可能带来Redis性能下降,因为持久化太过频繁会增大Redis服务的压力。
简单总结就是数据量太大、数据访问频率非常低的业务都不适合使用Redis。数据太大会增加成本,访问频率太低,保存在内存中纯属浪费资源。如果不担心浪费资源,那请忽略。
Redis为什么要用单线程
- 如果在多线程中操作,那就需要为这些对象加锁。所以使用多线程可以提高性能,但是每个线程的效率严重下降了,而且程序的逻辑严重复杂化。
- Redis的数据结构并不全是简单的Key-Value,还有list,hash等复杂的结构,这些结构有可能会进行很细粒度的操作,比如在很长的列表后面添加一个元素,在hash当中添加或者删除一个对象,这些操作还可以合成MULTI/EXEC的组。这样一个操作中可能就需要加非常多的锁,导致的结果是同步开销大大增加。Redis在权衡之后的选择是用单线程,突出自己功能的灵活性。在单线程基础上任何原子操作都可以几乎无代价地实现,多么复杂的数据结构都可以轻松运用,甚至可以使用Lua脚本这样的功能。对于多线程来说这需要高得多的代价。