Redis学习一:基础介绍
本文主要学习参考 菜鸟教程 ~~~
概述
Redis是高性能的key-value数据库
特点
- Redis 支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用;
- Redis 不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储;
- Redis 支持数据的备份,即master-slave模式的数据备份;
优势
- 性能极高 – Redis能读的速度是110000次/s,写的速度是81000次/s ;
- 丰富的数据类型 – Redis支持二进制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 数据类型操作;
- 原子 – Redis的所有操作都是原子性的,意思就是要么成功执行要么失败完全不执行。单个操作是原子性的。多个操作也支持事务,即原子性,通过MULTI和EXEC指令包起来;
- 丰富的特性 – Redis还支持 publish/subscribe, 通知, key 过期等等特性。
与其他key-value数据库的不同
- Redis有着更为复杂的数据结构并且提供对他们的原子性操作,这是一个不同于其他数据库的进化路径。Redis的数据类型都是基于基本数据结构的同时对程序员透明,无需进行额外的抽象;
- Redis运行在内存中但是可以持久化到磁盘,所以在对不同数据集进行高速读写时需要权衡内存,因为数据量不能大于硬件内存。在内存数据库方面的另一个优点是,相比在磁盘上相同的复杂的数据结构,在内存中操作起来非常简单,这样Redis可以做很多内部复杂性很强的事情。同时,在磁盘格式方面他们是紧凑的以追加的方式产生的,因为他们并不需要进行随机访问。
数据类型
数据类型基本介绍
- String
- Hash :key — value
- List :最多存储232-1个元素
- Set :String类型的无序集合,增改查复杂度为O(1),集合具有唯一性
- Zset :String类型的有序集合
- Stream : 消息的持久化 ,主备复制功能
各数据类型对应的应用场景
类型 | 简介 | 特性 | 场景 |
---|---|---|---|
String(字符串) | 二进制安全 | 可以包含任何数据,例如jpg图片或者序列化对象,一个键最大存储512M | 存储 |
Hash(字典) | 键值对集合,map | 适合存储对象,并且可以像数据库中update一个属性一样只修改某一项属性值 (Memcached中则需要取出整个字符串反序列化或对象修改完再序列化存回去 | 存储、读取、修改用户属性 |
List(列表) | 双向链表 | 增删快, 提供了操作某一段元素的API | 1. 最新消息排行等功能(例如朋友圈的时间线),2.消息队列 |
Set(集合) | 哈希表实现,元素不重复 | 1. 添加、删除、查找的复杂度都是O(1),2.为集合提供了求交集、并集、差集等操作 | 1. 共同好友 2. 利用唯一性,统计访问网站的所有独立ip 3. 好友推荐时根据tag求交集,大于某个阈值就可以推荐 |
Sorted Set(集合) | 将Set中的元素增加一个权重参数score,元素按照score有序排列 | 数据插入集合时,已经进行天然排序 | 1. 排行榜 2. 带权重的消息队列 |
Stream(流) | 维护一个消息链表,将所有加入的消息都串联起来,每一个消息都有唯一的ID和对应内容 | 提供消息的持久化和主从复制功能 | 1. 实时消息系统 2. 消息队列 |
发布与订阅
发布/订阅是一种消息通信模式:发送者 (pub) 发送消息,订阅者 (sub) 接收消息。Redis 客户端可以订阅任意数量的频道。下图展示了频道 channel1 , 以及订阅这个频道的三个客户端 —— client2 、 client5 和 client1 之间的关系:
当有新消息通过 PUBLISH 命令发送给频道 channel1 时, 这个消息就会被发送给订阅它的三个客户端:
发布/订阅功能可以应用的场景主要有:实时消息系统,即将信息回显到所有人、订阅-关注系统;而稍微复杂的场景 就应该使用消息中间件例如rocketmq来实现;
事务
redis可以一次执行多个命令,一个事务会经历三个阶段:开始事务、命令入队、执行事务;它执行时带有三个准则:【它不具有原子性】
1. 批量操作在发送 EXEC 命令前被放入队列缓存
2. 收到 EXEC 命令后进入事务执行,事务中任意命令执行失败,其余的命令依然被执行。
3. 在事务执行过程,其他客户端提交的命令请求不会插入到事务执行命令序列中。
客户端连接
Redis 通过监听一个 TCP 端口或者 Unix socket 的方式来接收来自客户端的连接,当一个连接建立后,Redis 内部会进行以下一些操作:
- 首先,客户端 socket 会被设置为非阻塞模式,因为 Redis 在网络事件处理上采用的是非阻塞多路复用模型;
- 然后为这个 socket 设置 TCP_NODELAY 属性,禁用 Nagle 算法;
- 最后创建一个可读的文件事件用于监听这个客户端 socket 的数据发送。
由于redis是一种基于客户端-服务端模型以及请求/响应协议的TCP服务。这意味着通常情况下一个请求会遵循以下步骤:
- 客户端向服务端发送一个查询请求,并监听Socket返回,通常是以阻塞模式,等待服务端响应;
- 服务端处理命令,并且将结果返回给客户端
Redis的管道技术在服务端未响应的时候, 客户端可以继续向服务端发送请求, 并最终一次性读取所有服务端的响应。它的优势就是可以提升redis服务的性能;
分区
分区是分割数据到多个Redis实例的处理过程,因此每个实例只保存key的一个子集。
分区类型
- 范围分区 : 映射一定范围的对象到特定的Redis实例,例如:R0保存ID从0到10000的用户,R1保存ID从10001到20000的用户
- 哈希分区:用一个hash函数将key转换为一个数字,假如具有4个redis实例,那么将该数字取模,就可以将该整数映射到4个中的一个了。
分区的优势
- 通过利用多台计算机内存的和值,允许我们构造更大的数据库;
- 通过多核和多台计算机,允许我们扩展计算能力;通过多台计算机和网络适配器,允许我们扩展网络带宽。
分区的不足
- 涉及多个key的操作通常是不被支持的。举例来说,当两个set映射到不同的redis实例上时,你就不能对这两个set执行交集操作。
- 涉及多个key的redis事务不能使用。
- 当使用分区时,数据处理较为复杂,比如你需要处理多个rdb/aof文件,并且从多个实例和主机备份持久化文件。
- 增加或删除容量也比较复杂。redis集群大多数支持在运行时增加、删除节点的透明数据平衡的能力,但是类似于客户端分区、代理等其他系统则不支持这项特性。然而,一种叫做presharding的技术对此是有帮助的。
Redis典型的应用场景
- 缓存热点数据: 经常被查询 , 但是不经常被修改或者删除的数据,首选使用redis缓存;
- 计数器: 统计点击量,访问量,点赞数,评论数,浏览数等应用,单线程可以避免并发问题,保证数据的正确性,并且100%毫秒级性能,同时开启Redis持久化,以便于持久化数据;
Redis是单线程!!!
- 单线程机制:每次请求的时候将Request IP、参数、key、接口返回参数等作为key存储到redis中,设置多长时间有效期,然后下次请求过来的时候先在redis中检索有没有这个key,进而验证是不是一定时间内过来的重复提交;再比如,限制用户登录的次数,比如一天错误登录次数10次等。
- 秒杀系统,基于redis是单线程的,这样可以有效防止出现数据库超卖的情况;
- 全局的增量ID生成;
- 排行榜:与计数器类似;
- 分布式锁:具有容错性,只要大部分redis节点正常运行,客户端就可以加锁与解锁;
- session存储:redis的优点在于:redis提供持久化;