介绍
redis是由C语言编写的写的 key-value 存储系统,是跨平台的非关系型数据库。遵守 BSD 协议、支持网络、可基于内存、分布式、可选持久性的键值对(Key-Value)存储数据库,并提供多种语言的 API。
Redis 通常被称为数据结构服务器,因为值(value)可以是字符串(String)、哈希(Hash)、列表(list)、集合(sets)和有序集合(zset)等类型。
Redis支持多个数据库,并且每个数据库的数据是隔离的不能共享,并且基于单机才有,如果是集群就没有数据库的概念
Redis是一个字典结构的存储服务器,而实际上一个Redis实例提供了多个用来存储数据的字典,客户端可以指定将数据存储在哪个字典中。这与我们熟知的在一个关系数据库实例中可以创建多个数据库类似,所以可以将其中的每个字典都理解成一个独立的数据库
每个数据库对外都是一个从0开始的递增数字命名,Redis默认支持16个数据库(可以通过配置文件支持更多,无上限),可以通过配置databases来修改这一数字。客户端与Redis建立连接后会自动选择0号数据库,不过可以随时使用SELECT命令更换数据库,如要选择1号数据库
然而这些以数字命名的数据库又与我们理解的数据库有所区别。首先Redis不支持自定义数据库的名字,每个数据库都以编号命名,开发者必须自己记录哪些数据库存储了哪些数据。另外Redis也不支持为每个数据库设置不同的访问密码,所以一个客户端要么可以访问全部数据库,要么连一个数据库也没有权限访问。最重要的一点是多个数据库之间并不是完全隔离的,比如FLUSHALL命令可以清空一个Redis实例中所有数据库中的数据。综上所述,这些数据库更像是一种命名空间,而不适宜存储不同应用程序的数据。比如可以使用0号数据库存储某个应用生产环境中的数据,使用1号数据库存储测试环境中的数据,但不适宜使用0号数据库存储A应用的数据而使用1号数据库B应用的数据,不同的应用应该使用不同的Redis实例存储数据。由于Redis非常轻量级,一个空Redis实例占用的内在只有1M左右,所以不用担心多个Redis实例会额外占用很多内存
使用
下面来实战测试一下,如果没有安装任何redis的窗口工具的话可以在redis的目录下
redis中默认端口号为6379,地址为127.0.0.1
我这里就直接在redis的工具中进行操作,没下载的可以去下载一个rdm管理工具
数据类型
String
String:redis中最简单的数据类型,一个 key 对应一个 value,redis中的String是二进制的,
所以说可以包含任何数据类型,最大的存储值为512MB
set name “藤井”
set:命令
name:键
藤井:值
get name
get:命令
name:键
通过get方法根据键找到对应的值
从这张管理工具的图发现添加之后的内容有
数据类型:String
键:name
值:藤井
键值大小:6 bytes
Hash
Hash:哈希是redis中的一个键值对集合,与java中的Map相似,是一个 string 类型的 field 和 value 的映射表
hash 特别适合用于存储对象,并且可以像数据库中update一个属性一样只修改某一项属性值(Memcached中需要取出整个字符串反序列化成对象修改完再序列化存回去)
每个 hash 可以存储键值对(40多亿)。
适用场景:存储、读取、修改用户属性
HMSET furit one “香蕉” two “苹果”
HMSET:哈希命令
fruit:集合名称
one:key值
香蕉:value值
HMGET furit one
HMGET:哈希命令
fruit:集合名称
one:key值
通过HMGET命令中的集合下的key去查找对应的value值
数据类型:HASH
集合名称:fruit
key:one
value:香蕉
List
List:列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)
列表最多可存储 元素 (4294967295, 每个列表可存储40多亿)。
链表(双向链表)增删快,提供了操作某一段元素的API
适用场景:1,最新消息排行等功能(比如朋友圈的时间线) 2,消息队列
Set
Redis 的 Set 是 string 类型的无序集合。
集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。
为集合提供了求交集、并集、差集等操作
添加一个 string 元素到 key 对应的 set 集合中,成功返回 1,如果元素已经在集合中返回 0。
sadd key member
适用场景
- 共同好友
- 利用唯一性,统计访问网站的所有独立ip
- 好友推荐时,根据tag求交集,大于某个阈值就可以推荐
在上面的示例中不难发现当我们添加第二次同样数据之后是为0,也将被忽略,同样的数据只会输出第一个,后面相同的数据将不会进入集合中
Zest
Zest: zset 和 set 一样也是string类型元素的集合,且不允许重复的成员
不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。
zset的成员是唯一的,但分数(score)却可以重复。
数据插入集合时,已经进行天然排序
适用场景
- 排行榜
- 带权重的消息队列
根据上面的示例看见有序集合的功效是会根据score去进行有序的排序,这就是有序集合
Redis命令
del key:删除指定的key
exists key:key是否存在,存在则输出1,不存在则输出0
expire key:为key设置过期时间,过期则失效
下面还有一些命令我直接总结就不再做示例
命令 | 描述 |
---|---|
Expireat | 以 UNIX 时间戳(unix timestamp)格式设置 key 的过期时间。key 过期后将不再可用 |
PEXPIRE | 设置 key 的过期时间以毫秒计 |
PEXPIREAT | 设置 key 过期时间的时间戳(unix timestamp) 以毫秒计 |
Keys | 查找所有符合给定模式( pattern)的 key |
Move | 将当前数据库的 key 移动到给定的数据库 db 当中 |
PERSIST | 移除给定 key 的过期时间,使得 key 永不过期 |
PTTL | 以毫秒为单位返回 key 的剩余的过期时间 |
TTL | 以秒为单位,返回给定 key 的剩余生存时间 |
RANDOMKEY | 从当前数据库中随机返回一个 key |
RENAME | 修改 key 的名称 |
RENAMENX key newkey | 仅当 newkey 不存在时,将 key 改名为 newkey |
SCAN cursor | 迭代数据库中的数据库键。 |
TYPE | 返回 key 所储存的值的类型 |
订阅者模式
Redis 发布订阅 (pub/sub) 是一种消息通信模式:发送者 (pub) 发送消息,订阅者 (sub) 接收消息。
Redis 客户端可以订阅任意数量的频道。
下图展示了频道 channel1 , 以及订阅这个频道的三个客户端 —— client2 、 client5 和 client1 之间的关系
当有新消息通过 PUBLISH 命令发送给频道 channel1 时, 这个消息就会被发送给订阅它的三个客户端
下面来实践操作试试
我们在redis管理工具内开启两个客户端窗口
在我们实例中我们创建了订阅频道名为name
打开第二个频道,然后在同一个频道 name发布次消息,订阅者就能接收到消息
对比第一张图,图1多了一个张三
Redis事务
Redis 事务可以一次执行多个命令, 并且带有以下三个重要的保证:
- 批量操作在发送 EXEC 命令前被放入队列缓存
- 收到 EXEC 命令后进入事务执行,事务中任意命令执行失败,其余的命令依然被执行
- 在事务执行过程,其他客户端提交的命令请求不会插入到事务执行命令序列中
redis开始到执行事务总共有三个阶段
开始事务、命令入队、执行事务
下面来做一个简单的例子看一下效果
一次性执行,首先由MULTI开头,以EXEC结尾,当中途不想执行事务的时候可以以discard命令取消事务
Redis Stream
Redis Stream 是 Redis 5.0 版本新增加的数据结构。
Redis Stream 主要用于消息队列(MQ,Message Queue),Redis 本身是有一个 Redis 发布订阅 (pub/sub) 来实现消息队列的功能,但它有个缺点就是消息无法持久化,如果出现网络断开、Redis 宕机等,消息就会被丢弃。
简单来说发布订阅 (pub/sub) 可以分发消息,但无法记录历史消息。
而 Redis Stream 提供了消息的持久化和主备复制功能,可以让任何客户端访问任何时刻的数据,并且能记住每一个客户端的访问位置,还能保证消息不丢失。
Redis Stream 的结构如下所示,它有一个消息链表,将所有加入的消息都串起来,每个消息都有一个唯一的 ID 和对应的内容
每个 Stream 都有唯一的名称,它就是 Redis 的 key,在我们首次使用 xadd 指令追加消息时自动创建。
使用 XADD 向队列添加消息,如果指定的队列不存在,则创建一个队列,例子如下,我添加了3条年龄
使用 XTRIM 对流进行修剪,限制长度
查看数据内容
使用 XDEL 删除消息
查看数据内容
可以发现这里我们刚刚添加了三条,但是在最后把年龄为12的删除了,所以最后的结果只有2条数据,这就是XDEL的功效