千家信息网

redis的高级特性有哪些

发表于:2025-01-20 作者:千家信息网编辑
千家信息网最后更新 2025年01月20日,这篇文章主要介绍了redis的高级特性有哪些,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。Redis(Remote Dictionar
千家信息网最后更新 2025年01月20日redis的高级特性有哪些

这篇文章主要介绍了redis的高级特性有哪些,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。

Redis(Remote Dictionary Server ),即远程字典服务,是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。

1.redis发布订阅模式

Redis除了提供像list的这种的消息队列模式,还提供了一组命令实现发布/订阅模式。例如微博,公众号等都是可以由此实现。

1.2 订阅频道

发布者需要将消息发送到一个地方,让订阅者可以订阅消息,这个地方就是频道(channel)。订阅者可以订阅一个或者多个频道,所有订阅了这个频道的订阅者都会受到这条消息。

开启两个客户端进行测试

客户端1 订阅channel1127.0.0.1:6379> subscribe channel1Reading messages... (press Ctrl-C to quit)1) "subscribe"2) "channel1"3) (integer) 1客户端2 发布一则消息127.0.0.1:6379> publish channel1 test(integer) 1客户端1 订阅消息127.0.0.1:6379> subscribe channel1Reading messages... (press Ctrl-C to quit)1) "subscribe"2) "channel1"3) (integer) 11) "message"2) "channel1"3) "test"

1.2 按规则订阅

支持?和*占位符。?代表一个字符,*代表 0 个或者多个字符。

启动四个redis-cli,一个作为消息的发布者,另外三个作为订阅者。
订阅者1:订阅体育相关

psubscribe *sport

订阅者2:订阅新闻相关

psubscribe news*

订阅者3:订阅天气相关

psubscribe new weather*

发布者:

publish news-sport Kobepublish news-music jaychoupublish news-weather rain

此时订阅者1将会收到Kobe,订阅者2将会收到全部信息,订阅者3将会收到rain。

2.redis事务

2.1 为什么要用事务

我们都是知道redis的单个命令是原子性的,但是如果需要用多个命令作为一个不可分割的操作序列,就需要用到事务。
例如使用setnx实现分布式锁,我们一般先set,然后对key设置expire,防止del发生异常时候锁不会释放,业务处理完之后在del,这三个操作我们就希望作为一组命令执行。
redis事务有两个特点:

  • 按照进入队列的顺序执行

  • 不会受到其他客户端请求影响

redis的事务设计四个命令:multi(开启事务),exec(执行事务),dicard(取消事务),watch(监视)

2.2 事务的用法

转账场景A和B各有100元,A向B转账10元,A减10元,B加10元

127.0.0.1:6379> set A 100OK127.0.0.1:6379> set B 100OK127.0.0.1:6379> multiOK127.0.0.1:6379> decrby A 10QUEUED127.0.0.1:6379> incrby B 10QUEUED127.0.0.1:6379> exec1) (integer) 902) (integer) 110127.0.0.1:6379> get A"90"127.0.0.1:6379> get B"110"

通过multi命令开启事务。事务不能嵌套,多个multi命令效果一样的
使用multi开启事务之后,客户端向服务器发送多条命令,这些命令并不会立即被执行,而是会被放到一个队列中,当exec命令调用之后,队列中的命令才会被执行。
我们可以使用discard来清空事务队列。

127.0.0.1:6379> multiOK127.0.0.1:6379> set k1 1QUEUED127.0.0.1:6379> set k2 2QUEUED127.0.0.1:6379> discardOK127.0.0.1:6379> get k1(nil)127.0.0.1:6379> get k2(nil)

当我们执行事务的时候出现了问题会回滚吗?

exec之前发生错误 (如指令语法错误)

127.0.0.1:6379> clear127.0.0.1:6379> multiOK127.0.0.1:6379> set name testQUEUED127.0.0.1:6379> hset user lisi(error) ERR wrong number of arguments for 'hset' command127.0.0.1:6379> exec(error) EXECABORT Transaction discarded because of previous errors.127.0.0.1:6379> get name(nil)

exec之后发生错误(对同一个key使用不同数据类型的命令)

127.0.0.1:6379> multiOK127.0.0.1:6379> set k1 1QUEUED127.0.0.1:6379> hset k1 a bQUEUED127.0.0.1:6379> exec1) OK2) (error) WRONGTYPE Operation against a key holding the wrong kind of value127.0.0.1:6379> get k1"1"

通过上面操作,我们可以知道当事务在exec前发生错误,将会回滚所有操作;如果在exec后发生错误,只有错误的命令不会被执行。
为什么redis在一个事务中存在错误不进行回滚呢?
我们从上面操作可以看出,redis只有在指令语法错误的时候进行回滚,而指令操作错误是有开发人员导致的bug,例如:你对一个int类型进行+1,然后不小心+2,或者对一个string类型进行+1,回滚是不适用的

2.3 watch指令

它可以为Redis事务提供CAS乐观锁操作,也就是多个线程更新某个变量的时候,会让旧值跟内存地址相比较,如果相等,则更新为新值。
我们可以用watch监视一个或者多个key,如果开启事务之后,至少有一个被监视的key在exec执行之前被修改,则会取消整个事务。

首先client 1执行watch监视money这个key,并开启事务对money进行增加100

127.0.0.1:6379> set money 1000OK127.0.0.1:6379> watch moneyOK127.0.0.1:6379> multiOK127.0.0.1:6379> incrby money 100QUEUED

在事务结束之前,在client 2对money进行减少100

127.0.0.1:6379> decrby money 100(integer) 900

此时client 1结束事务,money的值并没有被增加,反而减少,说明事务的修改失效

127.0.0.1:6379> exec(nil)127.0.0.1:6379> get money"900"

3. Lua脚本

Lua脚本是一种轻量级脚本语言,C语言编写的,跟存储过程有点类似。为啥要用lua脚本呢?

一次发送多个命令,减少网络开销Redis会将脚本作为一个整体执行,保证原子性(可用此方式替换事务)脚本复用,便于多个客户端完成相同的逻辑。

3.1 使用

我们可以使用以下命令进行调用lua脚本

eval script numkeys [key1 key2 key3 ....] [arg1 arg2 arg3 ....]

eval 执行lua脚本

script 代表lua脚本的内容

numkeys key的数量

[key1 key2 key3 ....] 键名参数,表示在脚本中所用到的那些 Redis 键(key),这些键名参数可以在 Lua 中通过全局变量 KEYS 数组,用 1 为基址的形式访问( KEYS[1] , KEYS[2] ,以此类推)。

[arg1 arg2 arg3 ....] 全局变量,可以在 Lua 中通过全局变量 ARGV 数组访问,访问的形式和 KEYS 变量类似( ARGV[1] 、 ARGV[2] ,诸如此类)

来个简单的例子

127.0.0.1:6379> eval "return {KEYS[1],ARGV[1],KEYS[2],ARGV[2]}" 2 key1 key2 val1 val11) "key1"2) "val1"3) "key2"4) "val1"127.0.0.1:6379> eval "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 key1 key2 val1 val11) "key1"2) "key2"3) "val1"4) "val1"

在lua脚本如何调用redis命令呢?
我们可以使用 redis.call(command, key [param1, param2…])进行操作

commond redis的命令,如set,get等key 被操作的键[param1, param2…]表示给key的参数

127.0.0.1:6379> eval "redis.call('mset',KEYS[1],ARGV[1],KEYS[2],ARGV[2])" 2 name age lisi 18(nil)127.0.0.1:6379> mget name age1) "lisi"2) "18

以上命令等价于 mset name lisi age 18, key的数量为2,2 后面两个值为key,在之后就是args

直接在redis-cli中写lua脚本不够方便,通常我们会把脚本放在文件中,然后执行这个文件
我们在一个目录下新建一个test.lua的脚本,填写以下内容后执行。

root@VM-0-5-centos src]# mkdir testlua[root@VM-0-5-centos src]# cd testlua/[root@VM-0-5-centos testlua]# lltotal 0[root@VM-0-5-centos testlua]# touch test.lua[root@VM-0-5-centos testlua]# vim test.luaredis.call('set',KEYS[1],ARGV[1])return redis.call('get',KEYS[1])[root@VM-0-5-centos testlua]# redis-cli --eval test.lua 1 myname , Armin"Armin"

值得注意的是key和arg之间需要加上空格逗号空格(myname , Armin)

3.2 缓存lua脚本

之所以需要缓存lua脚本,这是因为每次调用的时候都将整个脚本传给redis服务端,会产生较大的网络开销。为了解决这个问题,Redis提供了evalsha命令,让开发人员通过脚本内容的SHA1摘要执行脚本。

那么怎么将生成这个SHA1并将脚本内容加载到缓存呢,这就用到script load命令去计算脚本的SHA1摘要并记录脚本到缓存中,执行evalsha时,redis会根据提供的摘要去脚本缓存找到对应脚本内容,如果找到则执行,否则返回错误提示: "NOSCRIPT No matching script. Please use EVAL"

127.0.0.1:6379> script load "return 'Hey boy'""3760855b303510c83f0be2e8acfb0be64113ae6e"127.0.0.1:6379> evalsha 3760855b303510c83f0be2e8acfb0be64113ae6e 0"Hey boy"127.0.0.1:6379> script exists 3760855b303510c83f0be2e8acfb0be64113ae6e //判断是否存在1) (integer)

Redis还给lua脚本的执行提供了超时时间,默认的超时时间为5s,超过5s之后redis会接受其他命令但是会返回一个"BUSY"的错误
可在redis.conf中修改指定参数

lua-time-limit 5000

Redis提供了个script kill的命令来终止正在运行的脚本

127.0.0.1:6379> set name lisi(error) BUSY Redis is busy running a script. You can only call SCRIPT KILL or SHUTDOWN NOSAVE.127.0.0.1:6379> script killOK127.0.0.1:6379> set name lisiOK

如果数据进行了修改操作,将无法使用script kill终止脚本,因为违反了原子性。此时只能通过shutdown nosave来强行终止redis。
shutdown nosave 和 shutdown 的区别在于 shutdown nosave 不会进行持久化 操作,意味着发生在上一次快照后的数据库修改都会丢失。

感谢你能够认真阅读完这篇文章,希望小编分享的"redis的高级特性有哪些"这篇文章对大家有帮助,同时也希望大家多多支持,关注行业资讯频道,更多相关知识等着你来学习!

脚本 事务 命令 订阅 错误 订阅者 多个 客户 客户端 消息 内容 变量 时候 缓存 队列 频道 参数 指令 数据 篇文章 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 网络安全调查的对象范围 香港科技大学互联网 网络技术专业认知报告 360网络安全框架设施 数据库如何创建一对一关系 思迅服装之星9数据库名 我的世界加入服务器 倾杉网络技术 网络安全技术分析句子成分 数据库系统原理 国外课程 衡阳网络安全特训营费用多少 闪电网络技术是属于应用层 数据库管理系统的主要构成 戴尔服务器经销商 大连 国际知名数据库 某网站网络安全检查报告 湖北数据库空投箱出厂价格 sql语句提示数据库无法打开 电脑上怎么上服务器未响应 广州幸福网络技术有限公司 中兴通讯网络技术工程师做什么的 佳木斯网络安全局电话 数据库tno是指课程名吗 深圳网络安全法律法规比赛 互联网科技股今日走势 联想服务器td350 开机按钮 科技公司 软件开发增值税 网络安全常用的加密方法有四种 衢州酷特互联网科技服务有限公司 海南应用软件开发服务商
0