Redis数据库笔记

1.redis是什么?
  redis(REmote DIctionary Server)是一种使用C语言开发的NOSQL,即非关系数据库;Redis是一个操做数据结构的语言工具是一种内存数据库或者数据结构服务器,将数据直接保存在内存中,但又提供了持久化支持;是一种键值对数据库,保存的是键值对数据,至关于保存了一个变量及变量的值;以字典结构存储数据,并容许其余应用经过TCP协议读写字典中的内容;是Memcached缓存服务器的替代者。
2.redis能够用来作什么?
  数据库、队列、缓存系统,新浪微博大量使用了redis.Key-Value Store 是当下比较流行的话题,尤为在构建诸如搜索引擎、IM、P2P、游戏服务器、SNS等大型互联网应用以及提供云计算服务的时候,保证系统在海量数据环境下的高性能、高可靠性、高扩展性、高可用性、低成本.
适用场合:
a.取最新 N 个数据的操做
b.排行榜应用,取 TOP N 操做
c.须要精准设定过时时间的应用
d.计数器应用 INCR DECR
e.Uniq 操做,获取某段时间全部数据排重值
f.实时系统,反垃圾系统 SET集合
g.Pub/Sub 构建实时消息系统
h.构建队列系统
i.缓存
3.redis与memcashed的优劣
 在性能上Redis是单线程模型,而Memcached支持多线程,因此在多核服务器上后者的性能更高一些。然而,前面已经介绍过,Redis的性能已经足够优异,在绝大部分场合下其性能都不会成为瓶颈。因此在使用时更应该关心的是两者在功能上的区别,若是须要用到高级的数据类型或是持久化等功能,Redis将会是Memcached很好的替代品。
 做为缓存系统,Redis还能够限定数据占用的最大内存空间,在数据达到空间限制后能够按照必定的规则自动淘汰不须要的键。
 除此以外,Redis的列表类型键能够用来实现队列,而且支持阻塞式读取,能够很容易地实现一个高性能的优先级队列。同时在更高层面上,Redis还支持“发布/订阅”的消息模式,能够基于此构建聊天室等系统。
4.redis安装与启动
redis官方只提供了POSIX系统版的redis版本,http://download.redis.io/redis-stable.tar.gz能够下载最新的稳定版。redis没有其它外部依赖。在window中安装,须要使用cygwin环境。
服务器端启动:
>redis-server         :直接启动,默认端口6379
>redis-server --port 6380       :指定端口上启动
>redis-server redis.conf        :启动时使用配置文件初始化,redis.conf 位于安装文件中。
>redis-cli   SHUTDOWN           :安全终止redis服务器node

能够再主机的多个端口启动多个redis-server
客户端启动:
>redis-cli  -h 127.0.0.1 -p 6379     :客户端启动并链接服务器
5.redis命令执行的返回值(5种)
a.状态回复  回复命令的执行状态,如set和PING的回复
b.错误回复  命令执行错误,回复形式为:(error)...
c.整数回复  redis虽然没有整数类型,但提供了一组用于字符整数操做的命令,这些命令的回复返回整数,如INCR,DBSIZE ,回复形式为:(integer) n
e.字符串回复  当请求一个字符串类型键的键值或一个其余类型键中的某个元素时就会获得一个字符串回复,如GET,回复形式为:“...”
f.多行字符串回复  如KEYS命令,回复时会添加字符串行号。
6.redis的多数据库
    如mysql能够创建多个数据库同样,redis能够创建的数据库个数经过redis.conf中的databases来配置,默认为16个,数据库号从0-15,不支持自定义数据库名称。客户端redis-cli与Redis创建链接后会自动选择0号数据库,不过能够随时使用SELECT n命令更换数据库。
7.经常使用命令
KEYS glob_pattern     :查询当前数据库中全部的键glob_pattern : ?,*,[],\x
EXISTS key   :判断一个键是否存在,存在返回1,不然0
DEL key [key …] :删除一个或多个键
TYPE key  :返回key键的数据类型
EXPIRE key time  :设置一个键的过时时间
PERSIST key  :移除该键的过时时间
MOVE key n  :将当前数据库的key键移动到n号数据库
SELECT n  :选择n号数据库做为当前数据库,0-15
RANDOMKEY  :随机返回当前数据库的一个键
RENAME key newkey :重命名一个key
  服务器相关命令
PING   :测试链接是否存活
ECHO "..."  :在命令行打印一行内容
QUIT   :退出链接
DBSIZE   :返回当前数据库中键的个数
INFO   :返回服务器的信息和统计
MONITOR   :实时转储收到的请求
CONFIG GET dir  :获取服务器配置信息
FLUSHDB   :删除当前数据库中的全部key
FLUSHALL  :删除全部数据库中的keypython

8.redis的5大数据(键)类型
    字符串(string)、散列(hash)、列表(list)、集合(set)、有序集合(zset),每个键都是这5种数据类型中的一种,根据键的建立方式不一样来决定属于哪一种类型。Redis不支持数据类型嵌套。列表(list)、集合(set)、有序集合键只能保存字符串类型的数据。
a.字符串类型:一个字符串类型键容许存储的数据的最大容量是512MB。字符串类型是其余4种数据类型的基础,其余数据类型和字符串类型的差异从某种角度来讲只是组织字符串的形式不一样。例如,列表类型是以列表的形式组织字符串,而集合类型是以集合的形式组织字符串。
命令:
对字符串的操做
SET key value  :建立字符串变量并赋值
GET key   :当键不存在时会返回空结果。
SETNX key value  :若是键key不存在,则设置该键;存在则返回0,不进行设置
SETEX key time value  :设置键key的同时指定该键的有效期为time,可使用TTL查看
SETRANGE key start jointvalue :将键key从第8个字符起,替换为jointvalue
APPEND key value  :向一个字符串的尾部增长值
STRLEN key   :获取字符串长度
MSET key value [key value …] :同时设置多个键的值
MGET key [key …]  :同时获取多个键的值
MSETNX key value [key value …] :当失败时,一个键也不会被设置
GETSET key value  :设置并返回key的值
GETRANGE key start end  :返回key字符串中从start到end的子窜
对实数字符串的操做
INCR key   :递增数字,对非数字递增将返回错误
INCRBY key increment  :按指定数字增长
DECR key  :递减数字
DECRBY key decrement :按指定数字递减
INCRBYFLOAT key increment :对浮点数加
对字符串进行位操做的4大命令(是内存意义上的二进制位的操做)
GETBIT key offset  :获取字符串中总第offset位的二进制值
SETBIT key offset value  :设置字符串中总第offset位的二进制值
BITCOUNT key [m] [n]  :统一字符串中从第m字节到第n字节中的二进制数中的1的个数
BITOP operation destkey key [key …]:BITOP命令能够对多个字符串类型键进行位运算,并将结果存储在destkey参数指定的键中。BITOP命令支持的运算操做有AND、OR、XOR 和NOT
b.散列类型(python中的字典类型)
散列类型(hash)的键值是一种字典结构,其存储了字段(field)和字段值的映射,但字段值只能是字符串,不支持其余数据类型,一个散列类型键能够包含至多2的32次方-1个字段。
赋值与取值:
HSET key field value   :设置该键指定字段的值
HGET key field    :获取该键指定字段的值
HMSET key field value [field value …] :设置该键多个字段的值
HMGET key field [field …]  :获取该键多个字段的值
HGETALL key    :获取该键全部字段名及域值
HKEYS key    :获取该键全部字段名
HVALS key    :获取该键全部字段的值
HLEN key    :获取该键字段的个数
     
HEXISTS key field   :判断该键中是否存在某个字段
HSETNX key field value   :该字段不存在时赋值
HINCRBY key field increment  :对数字字符串加increment  
HDEL key field [field …]  :删除字段mysql

c.列表类型(双端链表)
向列表两端压入和弹出元素
LPUSH key value [value …]  :向列表左端添加元素
RPUSH key value [value …]  :向列表右端添加元素
LPOP key    :由列表左端弹出元素
RPOP key    :由列表右端弹出元素
LLEN key    :获取列表中元素的个数
LRANGE key start stop   :得到列表片断,-1,最后一个元素,-2倒数第二个元素
LREM key count value   :当count>会从左边删除列表中前count个值为value的元素,返回值是实际删除的元素个数;当count<0从右边起删除;count=0,会删除全部值为value的元素。
LINDEX key index   :得到指定索引的元素值,支持负索引
LSET key index value   :设置指定索引的元素值
LTRIM key start end   :只保留列表指定片断
LINSERT key BEFORE|AFTER pivot value :从左到右查找值为pivot的元素,将value插入到该元素的BEFORE或AFTER
RPOPLPUSH source destination  :将元素从一个列表的右边弹出转到另外一个列表的左边git

d.集合(存储不相同的字符串)
在集合中的每一个元素都是不一样的,且没有顺序。一个集合类型(set)键能够存储至多2次方32-1个(相信这个数字对你们来讲已经很熟悉了)字符串。集合类型的经常使用操做是向集合中加入或删除元素、判断某个元素是否存在等,因为集合类型在Redis内部是使用值为空的散列表(hash table)实现的,因此这些操做的时间复杂度都是0(1)。最方便的是多个集合类型键之间还能够进行并集、交集和差集运算。
SADD key member [member …]  :增长元素
SREM key member [member …]  :删除元素
SMEMBERS key    :得到集合中的全部元素
SISMEMBER key member   :判断元素是否在集合中
SDIFF key [key …]   :差集
SINTER key [key …]   :交集
SUNION key [key …]   :并集
SCARD key    :得到集合中元素个数
SDIFFSTORE destination key [key …] :进行集合运算并将结果存储
SINTERSTORE destination key [key …]
SUNIONSTORE destination key [key …]
SRANDMEMBER key [count]   :随机得到集合中的元素(默认1个)当count为正数时,SRANDMEMBER会随机从集合里得到count个不重复的元素。若是count的值大于集合中的元素个数,则SRANDMEMBER会返回集合中的所有元素;)当count为负数时,SRANDMEMBER会随机从集合里得到|count|个的元素,这些元素有可能相同。
SPOP key    :从集合中弹出一个元素
SMOVE source destination value  :将键source中的value移动到destination中。
e.有序集合类型(sorted set)
在集合类型的基础上有序集合类型为集合中的每一个元素都关联了一个分数,这使得咱们不只能够完成插入、删除和判断元素是否存在等集合类型支持的操做,还可以得到分数最高(或最低)的前N个元素、得到指定分数范围内的元素等与分数有关的操做。虽然集合中每一个元素都是不一样的,可是它们的分数却能够相同。
 有序集合类型在某些方面和列表类型有些类似。
(1)两者都是有序的。
(2)两者均可以得到某一范围的元素。
可是两者有着很大的区别,这使得它们的应用场景也是不一样的。
(1)列表类型是经过链表实现的,获取靠近两端的数据速度极快,而当元素增多后,访问中间数据的速度会较慢,因此它更加适合实现如“新鲜事”或“日志”这样不多访问中间元素的应用。
(2)有序集合类型是使用散列表和跳跃表(Skip list)实现的,因此即便读取位于中间部分的数据速度也很快(时间复杂度是O(log(N)))。
(3)列表中不能简单地调整某个元素的位置,可是有序集合能够(经过更改这个元素的分数)。
(4)有序集合要比列表类型更耗费内存
有序集合类型算得上是 Redis的5种数据类型中最高级的类型。github

ZADD key score member [score member …] :增长元素,score能够是任意实数
ZSCORE key member   :得到指定元素的分数
ZRANGE key start stop [WITHSCORES] :得到排名在某个范围的元素列表(升序),如前三ZRANGE key 0 2 ,[WITHSCORES]返回member的同时返回分数
ZREVRANGE key start stop [WITHSCORES] :按分数降序返回
ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count] :得到指定分数范围的成员(升序),[LIMIT offset count]从offset成员开始,返回count个成员
例 ZRANGEBYSCORE scoreboard (80 +inf LIMIT 5 3   返回80以上(不包括80)的从第5我的开始的3我的
Z INCRBY key increment member   :增长某个元素的分数,increment能够为负
ZCARD key    :得到集合中元素的个数
ZCOUNT key min max   :得到指定分数范围內的元素个数
ZREM key member [member …]  :删除一个或多个元素
ZREMRANGEBYRANK key start stop  :按照升序排名范围删除元素
ZREMRANGEBYSCORE key min max  :按照分数范围删除元素
ZRANK key member   :得到指定元素的升序排名
ZREVRANK key member   :得到指定元素的降序排名
ZINTERSTORE destination numkeys key [key …] [WEIGHTS weight [weight …]] [AGREGATE SUM|MIN|MAX] :计算有序集合的交集,若是权重相同,分数则按[AGREGATE SUM|MIN|MAX]计算
 
9.redis的事务
a.事务语法
redis的事务是须要原子执行的一组命令的集合。事务的原理是先将属于一个事务的命令发送给Redis,而后再让Redis依次执行这些命令。MULTI-EXEC关键字
redis>MULTI
OK
redis>SADD "user:1:following" 2
QUEUED
redis>SADD "user:2:followers" 1
QUEUED
redis>EXEC
1) (integer) 1
2) (integer) 1
在执行过程当中若是有语法错误,则离开返回;若是是其它错误(如命令与键值类型不匹配)则不返回,继续执行下面的命令,直到结束。不过因为Redis不支持回滚功能,也使得Redis在事务上能够保持简洁和快速。另外回顾刚才提到的会致使事务执行失败的两种错误,其中语法错误彻底能够在开发时找出并解决,另外若是可以很好地规划数据库(保证键名规范等)的使用,是不会出现如命令与数据类型不匹配这样的运行错误的。
b.监控-WATCH key
WATCH命令能够监控一个或多个键,一旦其中有一个键被修改(或删除),以后的事务就不会执行。监控一直持续到WATCH后面执行的第一个EXEC命令为止(事务中的命令是在EXEC以后才执行的,因此在MULTI命令后能够修改WATCH监控的键值)。
例子:
redis>SET key 1
OK
redis>WATCH key
OK
redis>SET key 2
OK
redis>MULTI
OK
redis>SET key 3
QUEUED
redis>EXEC  //在执行EXEC前,修改了WATCH监控的key值,因此WATCH紧跟的EXEC没有执行。
(nil)
redis>GET key
"2"redis

c.取消监控-UNWATCH -能够在EXEC以前,认为的取消监控
10.键的生存时间sql

EXPIRE key seconds  设置某个键的生存时间,时间到达后,键被删除;TTL key查看剩余的时间;PERSIST key取消生存时间
例子:
redis>SET foo bar
OK
redis>EXPIRE foo 20
(integer) 1
redis>TTL foo
(integer) 15
redis>TTL foo
(integer) 7
redis> TTL foo
(integer) -1 //键不存在,或者该键没有生存时间数据库

redis>EXPIRE foo 20
(integer) 1
redis>SET foo bar  //使用SET对键从新赋值,至关于删除该键,而后从新创建了一个新键
OK
redis>TTL foo
(integer) -1
 若是使用WATCH命令监测了一个拥有生存时间的键,该键时间到期自动删除并不会被WATCH命令认为该键被改变。
EXPIREAT  key stamps   时间戳,s单位
PEXPIREAT key stamps   时间戳,ms单位编程

11.排序
排序可使用有序集合,也可使用SORT命令。
SORT命令能够多LIST、SET、ZSET类型的key进行排序。
a.命令格式: SORT key [ALPHA] [DESC] LIMIT start end   :[ALPHA]表示按字母排序;默认是升序;LIMIT start end取排序结果的从start到end结果返回
b.SORT的BY参数:BY 参数的语法为“BY参考键”。其中参考键能够是字符串类型键或者是散列类型键的某个字段(表示为键名->字段名)。若是提供了BY参数,SORT命令将再也不依据元素自身的值进行排序,而是对每一个元素使用元素的值替换参考键中的第一个“*”并获取其值,而后依据该值对元素排序。参考键能够是散列或字符串类型。
例子:
redis>SORT tag:ruby:posts BY post:*->time DESC
1) "12"
2) "26"
3) "6"
4) "2"缓存

对字符串进行排序:参考键为字符串
redis>LPUSH sortbylist 2 1 3
(integer) 3
redis>SET itemscore:1 50
OK
redis>SET itemscore:2 100
OK
redis>SET itemscore:3 -10
OK
redis>SORT sortbylist BY itemscore:* DESC
1) "2"
2) "1"
3) "3"
例子中anytext是常量键名(甚至anytext键能够不存在),此时SORT的结果与LRANGE的结果相同,没有执行排序操做;若是几个元素的参考键值相同,则SORT命令会再比较元素自己的值来决定元素的顺序。
c.SORT的GET参数:GET参数不影响排序,它的做用是使SORT命令的返回结果再也不是元素自身的值,而是GET参数中指定的键值。GET参数的规则和BY参数同样,GET参数也支持字符串类型和散列类型的键,并使用“*”做为占位符。
redis>SORT tag:ruby:posts BY post:*->time DESC GET post:*->title
1) "Windows 8 app designs"
2) "RethinkDB - An open-source distributed database built with love"
3) "Uses for cURL"
4) "The Nature of Ruby"  
排序后返回的不是ID,而是ID对应的文章。(redis是否只能对数字和字母进行排序,不能对字符串进行排序?)
d.SORT的STORE参数:默认状况下SORT会直接返回排序结果,若是但愿保存排序结果,可使用STORE参数。
例子:
SORT some.list STORE cache.sort

12.消息通知
a.任务队列
说到队列很天然就能想到Redis的列表类型。若是要实现任务队列,只须要让生产者将任务使用LPUSH命令加入到某个键中,另外一边让消费者不断地使用RPOP命令从该键中取出任务便可。 BRPOP(右边出栈)和BLPOP(左边出栈) 命令就能够实现请求阻塞。
BRPOP命令接收两个参数,第一个是键名,第二个是超时时间,单位是秒。当超过了此时间仍然没有得到新元素的话就会返回nil。上例中超时时间为“0”,表示不限制等待的时间,即若是没有新元素加入列表就会永远阻塞下去。当得到一个元素后BRPOP命令返回两个值,分别是键名和元素值。
例子:(多个客户端实例中实现生产者与消费者模型)
在实例A中:
redis A>BRPOP queue 0
键入回车后实例1会处于阻塞状态,这时在实例B中向queue中加入一个元素:
redis B>LPUSH queue task
(integer) 1
在LPUSH命令执行后实例A立刻就返回告终果:
1) "queue"
2) "task"

b.优先级队列
BRPOP命令和BLPOP命令实际上能够同时阻塞的读取多个键,最前面的键优先级最高;若是全部键都没有元素则阻塞;若是都有元素,则先读取第一个键的元素。
BLPOP key [key …] timeout    :最前面的键具备更高的优先级
>LPUSH queue2 task2
1) (integer) 1
>LPUSH queue3 task3
1) (integer) 1
redis>BRPOP queue1 queue2 queue3 0
1) "queue:2"
2) "task2"

c.“发布/订阅”模式
    “发布/订阅”模式一样能够实现进程间的消息传递,其原理是这样的:“发布/订阅”模式中包含两种角色,分别是发布者和订阅者。订阅者能够订阅一个或若干个频道(channel),而发布者能够向指定的频道发送消息,全部订阅此频道的订阅者都会收到此消息。发布者发布消息的命令是PUBLISH,用法是:
PUBLISH channel message,如向channel.1说一声“hi”:
redis>PUBLISH channel.1 hi
(integer) 0
PUBLISH命令的返回值表示接收到这条消息的订阅者数量订阅频道的命令是SUBSCRIBE,能够同时订阅多个频道,用法是
SUBSCRIBEchannel[channel …]  如今新开一个redis-cli实例A,用它来订阅channel.1:
redis A>SUBSCRIBE channel.1
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "channel.1"
3) (integer) 1
执行SUBSCRIBE命令后客户端会进入订阅状态,处于此状态下客户端不能使用除SUBSCRIBE/UNSUBSCRIBE/PSUBSCRIBE/PUNSUBSCRIBE这4个属于“发布/订阅”模式的命令以外的命令(后面3个命令会在下面介绍),不然会报错。至关于阻塞在订阅模式中。UNSUBSCRIBE退订。

按照通配规则订阅:可使用PSUBSCRIBE命令按照通配规则订阅指定的规则
>PSUBSCRIBE channel.?*
Reading messages... (press Ctrl-C to quit)1) "psubscribe"
2) "channel.?*"
3) (integer) 1
 
redis B>PUBLISH channel.1 hi!
(integer) 2
订阅者返回结果:
1) "pmessage"
2) "channel.?*"
3) "channel.1"
4) "hi!"
 使用PSUBSCRIBE命令能够重复订阅一个频道,如某客户端执行了PSUBSCRIBE channel.? channel.?*,这时向channel.2发布消息后该客户端会收到两条消息,而同时PUBLISH命令返回的值也是2而不是1。
PUNSUBSCRIBE命令能够退订指定的规则,用法是
PUNSUBSCRIBE [pattern[pattern …]]
若是没有参数则会退订全部规则。
UNSUBSCRIBE命令只能退订经过PSUBSCRIBE命令订阅的规则,不会影响直接经过SUBSCRIBE命令订阅的频道;一样UNSUBSCRIBE命令也不会影响经过PSUBSCRIBE命令订阅的规则。另外容易出错的一点是使用PUNSUBSCRIBE命令退订某个规则时不会将其中的通配符展开,而是进行严格的字符串匹配,因此PUNSUBSCRIBE*没法退订channel.*规则,而是必须使用PUNSUBSCRIBE channel.*才能退订。

13.管道
    Redis的底层通讯协议对管道(pipelining)提供了支持。经过管道能够一次性发送多条命令并在执行完后一次性将结果返回,当一组命令中每条命令都不依赖于以前命令的执行结果时就能够将这组命令一块儿经过管道发出。管道经过减小客户端与Redis的通讯次数来实现下降往返时延累计值的目的。下降TCP消息包的数量。

14.redis与python
    Redis官方推荐的Python客户端是redis-py,见https://github.com/andymccurdy/redis-py
a.redis的python客户端在python编程中的使用方法:
import redis   //首先须要引入redis-py:
r=redis.StrictRedis()  //下面的代码将建立一个默认链接到地址127.0.0.1,端口6379的Redis链接:
r=redis.StrictRedis(host='127.0.0.1', port=6379, db=0)  //也能够显式地指定须要链接的地址:
r.set('foo', 'bar') # True
a=r.get('foo') # 'bar'
b.HMSET/HGETALL
HMSET支持将字典做为参数存储,同时HGETALL的返回值也是一个字典,搭配使用十分方便:
r.hmset('dict', {'name': 'Bob'})
people=r.hgetall('dict')
print people # {'name': 'Bob'}
c.事务和管道
redis-py的事务使用方式以下:
pipe=r.pipeline()
pipe.set('foo', 'bar')
pipe.get('foo')
result=pipe.execute()
print result # [True, 'bar']
管道的使用方式和事务相同,只不过须要在建立时加上参数transaction=False:
pipe=r.pipeline(transaction=False)
事务和管道还支持链式调用:
result=r.pipeline().set('foo', 'bar').get('foo').execute()
# [True, 'bar']

15.redis脚本
    Redis在2.6版推出了脚本功能,容许开发者使用Lua语言编写脚本传到Redis中执行。在Lua脚本中能够调用大部分的Redis命令
使用脚本的好处以下:
(1)减小网络开销:6.1节中的第一段代码最多须要向Redis发送5次请求,而使用脚本功能完成一样的操做只须要发送一个请求便可,减小了网络往返时延。
(2)原子操做:Redis会将整个脚本做为一个总体执行,中间不会被其余命令插入。换句话说在编写脚本的过程当中无需担忧会出现竞态条件,也就无需使用事务。事务能够完成的全部功能均可以用脚原本实现。
(3)复用:客户端发送的脚本会永久存储在Redis中,这就意味着其余客户端(能够是其余语言开发的项目)能够复用这一脚本而不须要使用代码完成一样的逻辑。
下面是一段lua脚本,名字为a.lua
local times=redis.call('incr', KEYS[1])
if times==1 then   -- KEYS[1]键刚建立,因此为其设置生存时间
redis.call('expire', KEYS[1], ARGV[1])
end
if times>tonumber(ARGV[2]) then
return 0
end
return 1
那么,如何测试这个脚本呢?首先把这段代码存为a.lua,而后在命名行中输入:
 redis-cli --eval a.lua rate.limiting:127.0.0.1 , 10 3
 
其中--eval 参数是告诉redis-cli读取并运行后面的Lua脚本,后面跟着的是传给Lua脚本的参数。其中“,”前的
rate.limiting:127.0.0.1是要操做的键,能够在脚本中使用KEYS[1]获取,“,”后面的10和3是参数,在脚本中
可以使用ARGV[1]和ARGV[2]得到。结合脚本的内容可知这行命令的做用就是将访问频率限制为每10秒最多3次,
因此在终端中不断地运行此命令会发现当访问频率在10秒内小于或等于3次时返回1,不然返回0。注意上面
的命令中“,”两边的空格不能省略,不然会出错。
16.redis与lua
a.在脚本中调用Redis命令
在脚本中可使用redis.call函数调用Redis命令。就像这样:
redis.call('set', 'foo', 'bar')
local value=redis.call('get', 'foo') --value的值为bar
redis.call函数的返回值就是Redis命令的执行结果。第2章介绍过Redis命令的返回值有5种
类型,redis.call函数会将这5种类型的回复转换成对应的Lua的数据类型.
Redis还提供了redis.pcall函数,功能与redis.call相同,惟一的区别是当命令执行出错时redis.pcall会记录错误并继续执行,而redis.call会直接返回错误,不会继续执行。
b. 从脚本中返回值 return
在脚本中可使用return语句将值返回给客户端,若是没有执行return语句则默认返回nil。由于咱们能够像调用其余Redis内置命令同样调用咱们本身写的脚本
c. 脚本相关命令EVAL命令:EVAL命令的格式是:EVAL脚本内容key参数的数量[key …] [arg …]能够经过key和arg这两类参数向脚本传递数据,它们的值能够在脚本中分别使用KEYS和ARGV两个表类型的全局变量访问例如,咱们但愿用脚本功能实现一个SET命令(固然现实中咱们不会这么干),脚本内容是这样的:return redis.call('SET', KEYS[1], ARGV[1])如今打开redis-cli执行此脚本:redis>EVAL "return redis.call('SET', KEYS[1], ARGV[1])" 1 foo barOKredis>GET foo"bar"EVALSHA命令:考虑到在脚本比较长的状况下,若是每次调用脚本都须要将整个脚本传给Redis会占用较多的带宽。为了解决这个问题,Redis提供了EVALSHA命令容许开发者经过脚本内容的SHA1摘要来执行脚本,该命令的用法和EVAL同样,只不过是将脚本内容替换成脚本内容的SHA1摘要.在程序中使用EVALSHA命令的通常流程以下:(1)先计算脚本的SHA1摘要,并使用EVALSHA命令执行脚本。(2)得到返回值,若是返回“NOSCRIPT”错误则使用EVAL命令从新执行脚本。虽然这一流程略显麻烦,但值得庆幸的是不少编程语言的Redis客户端都会代替开发者完成这一流程。好比使用node_redis客户端执行EVAL命令时,node_redis会先尝试执行EVALSHA命令,若是失败了才会执行EVAL命令

相关文章
相关标签/搜索