01 Redis是什么?
Redis是C语言编写完全开源免费的,遵守BSD协议,是一个高性能的key-value数据库,而且是一个NOSQL类型数据库,是为了解决高并发、高扩展,大数据存储等一系列的问题而产生的数据库解决方案。但是,它也是不能替代关系型数据库,只能作为特定环境下的扩充。
02 Redis的特点有哪些?
Redis本质上是一个Key-Value类型的内存数据库。其有以下三个特点:
- Redis 支持数据持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。
- Redis 不仅仅支持简单的 key - value 类型的数据,同时还提供 list,set,zset,hash 等数据结构的存储
- Redis 支持数据的备份,即 master - slave 模式的数据备份
03 Redis支持的数据类型
Redis支持 5 中数据类型:string(字符串),hash(哈希),list(列表),set(集合),zset(sorted set:有序集合)。
string
string 是 redis 最基本的数据类型。一个 key 对应一个 value。
string 是二进制安全的。也就是说 redis 的 string 可以包含任何数据。比如 jpg 图片或者序列化的对象。
string 类型是 redis 最基本的数据类型,string 类型的值最大能存储 512 MB。
理解:string 就像是 java 中的 map 一样,一个 key 对应一个 value
hash
Redis hash 是一个键值对(key - value)集合。
Redis hash 是一个 string 类型的 key 和 value 的映射表,hash 特别适合用于存储对象。
理解:可以将 hash 看成一个 key - value 的集合。也可以将其想成一个 hash 对应着多个 string。
与 string 区别:string 是 一个 key - value 键值对,而 hash 是多个 key - value 键值对。
list
Redis 列表是简单的字符串列表,按照插入顺序排序。我们可以网列表的左边或者右边添加元素。
我们可以看出 list 就是一个简单的字符串集合,和 Java 中的 list 相差不大,区别就是这里的 list 存放的是字符串。list 内的元素是可重复的。
set
redis 的 set 是字符串类型的无序集合。集合是通过哈希表实现的,因此添加、删除、查找的复杂度都是 O(1)。
redis 的 set 与 java 中的 set 还是有点区别的。redis 的 set 是一个 key 对应着 多个字符串类型的 value,也是一个字符串类型的集合,但是和 redis 的 list 不同的是 set 中的字符串集合元素不能重复,但是 list 可以。
Zset
redis zset 和 set 一样都是 字符串类型元素的集合,并且集合内的元素不能重复。
不同的是 zset 每个元素都会关联一个 double 类型的分数。redis 通过分数来为集合中的成员进行从小到大的排序。
zset 的元素是唯一的,但是分数(score)却可以重复。
zset 是按照 分输的大小来排序的。
04 为什么Redis需要把所有数据放到内存中?
Redis为了达到最快的读写速度将数据都读到内存中,并通过异步的方式将数据写入磁盘。所以Redis具有快速和数据持久化的特性。
如果不将数据放到内存中,磁盘的I/O速度会严重影响redis的性能。在内存越来越便宜的今天,redis将会越来越受欢迎。如果设置了最大使用的内存,则数据已有记录数达到内存限值后将不能继续插入新值。
05 Redis 适用场景有哪些?
1、缓存
缓存现在几乎是所有中大型网站都在用的必杀技,将业务中的热数据存储在Redis中,合理的利用缓存不仅能够提升网站访问速度,还能大大降低数据库的压力。Redis提供了键过期功能,也提供了灵活的键淘汰策略,所以,现在Redis用在缓存的场合非常多。
2、排行榜
很多网站都有排行榜应用的,如京东的月度销量榜单、商品按时间的上新排行榜等。Redis提供的SortedSet (有序集合)数据类构能实现各种复杂的排行榜功能。SortedSet 类型每个成员具有两个属性,一个是 name 一个是 score, 使用 zadd key score member 向 SortedSet 添加成员。使用 zrevrange key start stop 来获取指定排名区间的成员(zrevrange 按 score 从大到小排列,zrange相反)。
3、计数器 & 计时
可实现计数和计时的功能。如电商网站商品的浏览量、视频网站视频的播放数等。为了保证数据实时效,每次浏览都得给+1,并发量高时如果每次都请求数据库操作无疑是种挑战和压力。再比如每天最多只能获取10次验证码, 可以使用 Redis 提供的 inch 命令, inch会对数据进行加一操作而且该命令具有原子性。非常适用于这些计数场景。
计时,比如验证码一分钟内有效。可以使用 Redis 的 setex 命令设置验证码只保存一分钟,一分钟后失效。
4、分布式会话
集群模式下,在应用不多的情况下一般使用容器自带的session复制功能就能满足,当应用增多相对复杂的系统中,一般都会搭建以Redis等内存数据库为中心的session服务,session不再由容器管理,而是由session服务及内存数据库管理。
5、分布式锁
在很多互联网公司中都使用了分布式技术,分布式技术带来的技术挑战是对同一个资源的并发访问,如全局ID、减库存、秒杀等场景,并发量不大的场景可以使用数据库的悲观锁、乐观锁来实现,但在并发量高的场合中,利用数据库锁来控制资源的并发访问是不太理想的,大大影响了数据库的性能。可以利用Redis的setnx实现锁机制。setnx == set if not exsist。用法为 setnx key value 。如果该key存在则设置不成功返回0, 如果该 key 不存在则设置成功返回1。 能够设置成功则获得锁,设置不成功则获取不到锁。当然还要考虑获得锁的进程挂掉/网络连接失败 导致的死锁等情况。,实际应用中要考虑的细节要更多。
6、 社交网络
点赞、踩、关注/被关注、共同好友等是社交网站的基本功能,社交网站的访问量通常来说比较大,而且传统的关系数据库类型不适合存储这种类型的数据,Redis提供的哈希、集合等数据结构能很方便的的实现这些功能。
7、最新列表
Redis列表结构,LPUSH可以在列表头部插入一个内容ID作为关键字,LTRIM可用来限制列表的数量,这样列表永远为N个ID,无需查询最新的列表,直接根据ID去到对应的内容页即可。
8、消息系统
消息队列是大型网站必用中间件,如ActiveMQ、RabbitMQ、Kafka等流行的消息队列中间件,主要用于业务解耦、流量削峰及异步处理实时性低的业务。Redis提供了发布/订阅及阻塞队列功能,比如email或者验证码的发送队列,Redis的List类型能够很轻松的实现一个消息队列,使用lpush和rpop/brpop(阻塞版rpop)。另外,这个不能和专业的消息中间件相比。