一、关于Redis
Redis是一款开源的、使用 C 语言编写的 NoSQL 数据库。
Redis基于内存运行、支持持久化,采用key-value存储形式,应用在分布式架构中。
Redis服务器程序是单进程模型,在一个服务器中可同时启动多个Redis进程。
当服务器只有一个Redis进程时有多个客户端并发,这时服务器的处理能力会降低;
当服务器中有多个Redis进程时,服务器处理能力提升,但会提高CPU占用率。
二、Redis的优点
- 读写速度快
- 支出多种数据类型(value):
String: 字符串
Hash: 散列
List: 列表
Set: 集合
Sorted Set: 有序集合
- 所有操作都是原子性的
- 支持数据备份
- 支持数据持久化:内存数据存储在磁盘中,每次重启加载数据
三、redis的部署
1.命令redis-server.exe redis.windows.conf 或redis-server.exe启动redis服务
D:\Redis>redis-server.exe redis.windows.conf [21100] 30 Jun 16:14:42.313 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo [21100] 30 Jun 16:14:42.314 # Redis version=5.0.14.1, bits=64, commit=ec77f72d, modified=0, pid=21100, just started [21100] 30 Jun 16:14:42.314 # Configuration loaded _._ _.-``__ ''-._ _.-`` `. `_. ''-._ Redis 5.0.14.1 (ec77f72d/0) 64 bit .-`` .-```. ```\/ _.,_ ''-._ ( ' , .-` | `, ) Running in standalone mode |`-._`-...-` __...-.``-._|'` _.-'| Port: 6379 | `-._ `._ / _.-' | PID: 21100 `-._ `-._ `-./ _.-' _.-' |`-._`-._ `-.__.-' _.-'_.-'| | `-._`-._ _.-'_.-' | http://redis.io `-._ `-._`-.__.-'_.-' _.-' |`-._`-._ `-.__.-' _.-'_.-'| | `-._`-._ _.-'_.-' | `-._ `-._`-.__.-'_.-' _.-' `-._ `-.__.-' _.-' `-._ _.-' `-.__.-' [21100] 30 Jun 16:14:42.319 # Server initialized [21100] 30 Jun 16:14:42.337 * DB loaded from disk: 0.017 seconds [21100] 30 Jun 16:14:42.337 * Ready to accept connections
2.打开新终端
启动redis服务端
D:\>cd redis
D:\Redis>redis-cli.exe
127.0.0.1:6379>
远程连接执行命令
$ redis-cli -h host -p port -a password
四、redis : Key-Value
1.键(key)-- COMMAND KEY_NAME
127.0.0.1:6379> set key_name value //设置键-值
OK
127.0.0.1:6379> get key_name //查看key-name的值
"value"
127.0.0.1:6379> EXISTS key_name //查看key_name键是否存在 存在返回1|不存在返回0
(integer) 1
127.0.0.1:6379> set new 'hello world!'
OK
127.0.0.1:6379> DUMP new //DUMP序列化键值
"\x00\x0chello world!\t\x00\xe5\x8d/\xa41\t\xaci"
127.0.0.1:6379> KEYS * //查看所有键
1) "new"
2) "key_name"
127.0.0.1:6379> type key_name //查看键 key_name 存储值类型
string
127.0.0.1:6379> RANDOMKEY //随机输出键
"new"
127.0.0.1:6379> rename key_name name //重命名key
OK
127.0.0.1:6379> keys *
1) "name"
2) "str"
127.0.0.1:6379> FLUSHDB //删除所有KEY
OK
127.0.0.1:6379> KEYS *
(empty list or set)
2.字符串(String)
127.0.0.1:6379> set name lihao
OK
127.0.0.1:6379> getrange name 0 2 //获取0-2 name键值
"lih"
127.0.0.1:6379> getset name lihao- //重置name的值,并打印原来值
"lihao"
127.0.0.1:6379> mget name str //批量打印 键对应值
1) "lihao-"
2) "Hello world"
127.0.0.1:6379> append name 77 //name键后追加字符
(integer) 8
127.0.0.1:6379> get name
"lihao-77"
3.哈希(Hash) field-value (字段-值)对
Redis hash 是 string 类型的 field(字段) 和 value(值) 的映射表,相当于在redis键值对中嵌套了一层key-value,适合用于存储关系型对象。
hash 类型的 (key, field, value) 的结构与对象的(对象id, 属性, 值)的结构相似,效率高、容量低、灵活性高、序列化复杂。可用于商品管理,需要频繁修改的商品名称、价格、简介等
127.0.0.1:6379> hmset students id 1 name liahao age 21 sex male
OK //设置student表 属性id、name、age、sex
127.0.0.1:6379> hmget students id name sex //打印student表属性值
1) "1"
2) "liahao"
3) "male"
127.0.0.1:6379> rename students std //重命名表名
OK
127.0.0.1:6379> keys * //打印所有key
1) "name"
2) "key"
3) "str"
4) "std"
127.0.0.1:6379> hmget std id name sex //打印std表指定属性值
1) "1"
2) "liahao"
3) "male"
127.0.0.1:6379> hvals std //打印表std所有值
1) "1"
2) "liahao"
3) "21"
4) "male"
127.0.0.1:6379> hgetall std //打印表std所有键、值
1) "id"
2) "1"
3) "name"
4) "liahao"
5) "age"
6) "21"
7) "sex"
8) "male"
127.0.0.1:6379> hdel std sex //删除指定键值
(integer) 1
127.0.0.1:6379> hvals std
1) "1"
2) "liahao"
3) "21"
4.列表(List)
Redis列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边),可以将List
看成栈、队列等、
127.0.0.1:6379> lpush list fruit //从开头插入数据
(integer) 1
127.0.0.1:6379> lpush list animal
(integer) 2
127.0.0.1:6379> lpush list color
(integer) 3
127.0.0.1:6379> lrange list 0 2 //打印数据0-2
1) "color"
2) "animal"
3) "fruit"
127.0.0.1:6379> BLPOP list 5 //从开头弹出元素 若set1无数据,等待5s返回nil
1) "set1"
2) "color"
127.0.0.1:6379> lrange list 0 2 //弹出set1 首元素成功
1) "animal"
2) "fruit"
127.0.0.1:6379> blpop list 5
(nil)
(10.09s)
127.0.0.1:6379> llen list //打印列表长度
(integer) 2
127.0.0.1:6379> lset list 2 color //将第二个数据值修改为 color
OK
127.0.0.1:6379> lrange list 0 10
1) "3"
2) "2"
3) "color"
4) "fruit"
5) "animal"
5.集合(Set)
Redis 的 Set 是 String 类型的无序集合,集合成员是唯一的。
通过哈希表实现,添加,删除,查找的复杂度都是 O(1)
127.0.0.1:6379> sadd set a b c //向集合set中插入元素
(integer) 3
127.0.0.1:6379> scard set //打印集合set中元素个数
(integer) 3
127.0.0.1:6379> sismember set a //判断a是否是set集合的元素
(integer) 1
127.0.0.1:6379> spop set //移除并返回任意元素
"a"
127.0.0.1:6379> srandmember set 2 //返回集合中任意2个元素
1) "b"
2) "c"
6.有序集合(ordered sets)
Redis 有序集合也是 string 类型元素的集合,且不允许重复的成员。
有序集合每个元素都会关联一个 double 类型的分数。redis通过分数来为集合中的成员进行从小到大的排序。有序集合的成员是唯一的,但分数(score)却可以重复。
通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)
127.0.0.1:6379> zadd ordset 1 a //插入元素a 分数为1
(integer) 1
127.0.0.1:6379> zadd ordset 2 b 2 c 3 r
(integer) 3
127.0.0.1:6379> zadd ordset 1 g
(integer) 1
127.0.0.1:6379> zrange ordset 0 10 //打印0-10的元素
1) "a"
2) "g"
3) "b"
4) "c"
5) "r"
127.0.0.1:6379> zcard ordset //获取有序集合的成员数
(integer) 5
127.0.0.1:6379> zcount ordset 1 2 //计算在有序集合中指定区间分数的成员数
(integer) 4
127.0.0.1:6379> zincrby ordset 5 b //有序集合中对指定成员b的分数加上增量 5
"7"
127.0.0.1:6379> zrange ordset 0 10
1) "a"
2) "g"
3) "c"
4) "r"
5) "b"
127.0.0.1:6379> zscore ordset r //返回有序集中,成员的分数值
"3"
127.0.0.1:6379> zrevrank ordset c //返回有序集合c成员的排名,按分数值递减(从大到小)排序
(integer) 2
127.0.0.1:6379> zremrangebyscore ordset 0 3 //移除有序集合中给定的分数区间的所有成员
(integer) 4
127.0.0.1:6379> zrange ordset 0 10
1) "b"
五、redis 发布订阅
![](https://img-blog.csdnimg.cn/direct/81b8c9f0f016464a94bd9fc5f046ba9b.png)
原理:
通过 SUBSCRIBE 命令订阅某频道后,redis-server 里维护了一个字典,字典的键就是一个个 channel ,而字典的值则是一个链表,链表中保存了所有订阅这个 channel 的客户端。SUBSCRIBE 命令的关键,就是将客户端添加到给定 channel 的订阅链表中。
通过 PUBLISH 命令向订阅者发送消息,redis-server 会使用给定的频道作为键,在它所维护的 channel 字典中查找记录了订阅这个频道的所有客户端的链表,遍历这个链表,将消息发布给所有订阅者。
发布订阅使用场景
1、异步消息通知
调用支付平台(支付/收款订阅同一频道,一个订单一个频道)
2、任务通知
定时发布任务->channel->系统触发任务
3、参数刷新加载
点击刷新->channel->数据加载
六、redis事务
Redis事务:
多个命令组成队列,每次执行一个命令,顺序执行。
客户端命令不会插入到事务执行命令中
- 批量操作在发送 EXEC 命令前被放入队列缓存。
- 收到 EXEC 命令后进入事务执行,事务中任意命令执行失败,其余的命令依然被执行。
- 在事务执行过程,其他客户端提交的命令请求不会插入到事务执行命令序列中。
一个事务从开始到执行会经历以下三个阶段:
- 开始事务
- 命令入队
- 执行事务
单个 Redis 命令的执行是原子性的,但 Redis 没有在事务上增加任何维持原子性的机制,所以 Redis 事务的执行并不是原子性的。
事务可以理解为一个打包的批量执行脚本,但批量指令并非原子化的操作,中间某条指令的失败不会导致前面已做指令的回滚,也不会造成后续的指令不做。
实例:
127.0.0.1:6379> multi //multi开始事物
OK
127.0.0.1:6379> sadd name-key C Python Javascript Shell
QUEUED
127.0.0.1:6379> smembers name-key
QUEUED
127.0.0.1:6379> exec //exec触发事物
1) (integer) 4
2) 1) "Python"
2) "C"
3) "javascript"
4) "Shell"