非常教程

Redis参考手册

字符串 | Strings

incr

INCR key

自1.0.0起可用。

时间复杂度: O(1)

将存储的数字key加1。如果密钥不存在,则0在执行操作之前将其设置为。如果密钥包含错误类型的值或包含无法表示为整数的字符串,则会返回错误。该操作仅限于64位有符号整数。

注意:这是一个字符串操作,因为Redis没有专用的整数类型。存储在密钥中的字符串被解释为一个以10为底的64位有符号整数来执行操作。

Redis 以整数表示形式存储整数,因此对于实际上包含整数的字符串值,不存在用于存储整数的字符串表示形式的开销。

返回值

整数回复:key增量后的值

例子

redis> SET mykey "10" "OK" redis> INCR mykey (integer) 11 redis> GET mykey "11"

模式:计数器

计数器模式是使用 Redis 原子增量操作可以做的最明显的事情。这个想法只是在每次操作发生时发送 INCR 命令给 Redis。例如,在一个 Web 应用程序中,我们可能想知道这个用户一年中每天都做了多少页面浏览。

为此,Web 应用程序可以在每次用户执行页面视图时简单地增加一个键,创建连接用户 ID 的键名和代表当前日期的字符串。

这种简单模式可以通过多种方式进行扩展:

  • 可以在每个页面视图中一起使用 INCR 和 EXPIRE,使计数器只计算最近 N 个分页少于指定秒数的页面视图。
  • 客户端可以使用 GETSET 来自动获取当前计数器值并将其重置为零。
  • 使用其他原子增量/减量命令(如 DECR 或 INCRBY),可以根据用户执行的操作来处理可能变大或变小的值。想象一下在线游戏中不同用户的分数。

模式:限速器

速率限制器模式是一个特殊的计数器,用于限制执行操作的速率。这种模式的经典实现涉及限制可以针对公共 API 执行的请求的数量。

我们使用 INCR 提供了这种模式的两种实现,我们假设要解决的问题是将 API 调用的数量限制为每IP地址每秒最多10个请求

模式:限速器1

这种模式的更简单直接的实现如下:

FUNCTION LIMIT_API_CALL(ip)
ts = CURRENT_UNIX_TIME()
keyname = ip+":"+ts
current = GET(keyname)
IF current != NULL AND current > 10 THEN
    ERROR "too many requests per second"
ELSE
    MULTI
        INCR(keyname,1)
        EXPIRE(keyname,10)
    EXEC
    PERFORM_API_CALL()
END

基本上我们有每个IP的柜台,每隔一秒钟。但是这个计数器总是递增的,设置10秒过期,以便在当前秒不同时自动将它们由 Redis移除。

请注意使用 MULTI 和 EXEC,以确保我们在每次 API 调用时都会递增并设置到期。

模式:限速器2

另一种实现方法是使用单个计数器,但要在没有竞争条件的情况下进行正确的设置会更复杂一些。我们将研究不同的变体。

FUNCTION LIMIT_API_CALL(ip):
current = GET(ip)
IF current != NULL AND current > 10 THEN
    ERROR "too many requests per second"
ELSE
    value = INCR(ip)
    IF value == 1 THEN
        EXPIRE(ip,1)
    END
    PERFORM_API_CALL()
END

计数器的创建方式只能在当前秒的第一次请求开始后才能存活一秒。如果在同一秒内有超过10个请求,则计数器将达到大于10的值,否则将过期并从0开始。

在上面的代码中有一个竞争条件。如果由于某种原因,客户端执行INCR 命令但不执行 EXPIRE,密钥将被泄露,直到我们再次看到相同的IP地址。

这可以很容易地解决,将带有可选 EXPIRE 的 INCR 转换为使用EVAL 命令发送的 Lua 脚本(仅在 Redis 版本2.6以后可用)。

local current
current = redis.call("incr",KEYS[1])
if tonumber(current) == 1 then
    redis.call("expire",KEYS[1],1)
end

有一种不使用脚本解决此问题的方法,但使用 Redis 列表而不是计数器。实现更复杂,使用更多高级功能,但具有记住当前正在执行API调用的客户端的IP地址的优点,根据应用程序的不同,该地址可能有用或无用。

FUNCTION LIMIT_API_CALL(ip)
current = LLEN(ip)
IF current > 10 THEN
    ERROR "too many requests per second"
ELSE
    IF EXISTS(ip) == FALSE
        MULTI
            RPUSH(ip,ip)
            EXPIRE(ip,1)
        EXEC
    ELSE
        RPUSHX(ip,ip)
    END
    PERFORM_API_CALL()
END

如果密钥已经存在,RPUSHX 命令只会推送元素。

请注意,我们在这里有一场竞赛,但这不是问题:在我们在MULTI / EXEC 块中创建它之前,EXISTS 可能会返回 false,但可能会由另一个客户端创建密钥。然而,这种竞争只会在极少数情况下错过API调用,所以速率限制仍然可以正常工作。

Redis

Redis 是一个开源的使用 ANSI C 语言编写、遵守 BSD 协议、支持网络、可基于内存亦可持久化的日志型、Key-Value 数据库,并提供多种语言的 API。 它通常被称为数据结构服务器,因为值( value )可以是 字符串( String ), 哈希(Map),列表(list),集合( sets ) 和 有序集合( sorted sets )等类型。

主页 https://redis.io/
源码 https://github.com/antirez/redis
发布版本 4.0.2

Redis目录

1.集合 | Cluster
2.连接 | Connection
3.Geo
4.Hashes
5.HyperLogLog
6.键 | Keys
7.列表 | Lists
8.Pub/Sub
9.脚本 | Scripting
10.服务器 | Server
11.设定 | Sets
12.排序集 | Sorted Sets
13.字符串 | Strings
14.事务 | Transactions
15.Redis Dump 命令
16.Redis DEL 命令
17.Redis 键(key)
18.Redis 命令
19.Redis 配置
20.Redis 简介
21.Redis RANDOMKEY 命令
22.Redis TTL 命令
23.Redis Pttl 命令
24.Redis PERSIST 命令
25.Redis Move 命令
26.Redis PEXPIREAT 命令
27.Redis Keys 命令
28.Redis Expireat 命令
29.Redis Expire 命令
30.Redis EXISTS 命令
31.Redis Mget 命令
32.Redis Getbit 命令
33.Redis Getset 命令
34.Redis Getrange 命令
35.Redis Get 命令
36.Redis SET 命令
37.Redis 字符串(String)
38.Redis Type 命令
39.Redis Renamenx 命令
40.Redis Rename 命令
41.Redis Incrby 命令
42.Redis Incr 命令
43.Redis Psetex 命令
44.Redis Msetnx 命令
45.Redis Mset 命令
46.Redis Strlen 命令
47.Redis Setrange 命令
48.Redis Setnx 命令
49.Redis Setex 命令
50.Redis Setbit 命令
51.Redis Hincrby 命令
52.Redis Hgetall 命令
53.Redis Hget 命令
54.Redis Hexists 命令
55.Redis Hdel 命令
56.Redis 哈希(Hash)
57.Redis Append 命令
58.Redis Decrby 命令
59.Redis Decr 命令
60.Redis Incrbyfloat 命令
61.Redis Blpop 命令
62.Redis 列表(List)
63.Redis Hvals 命令
64.Redis Hsetnx 命令
65.Redis Hset 命令
66.Redis Hmset 命令
67.Redis Hmget 命令
68.Redis Hlen 命令
69.Redis Hkeys 命令
70.Redis Hincrbyfloat 命令
71.Redis Lrem 命令
72.Redis Lrange 命令
73.Redis Lpushx 命令
74.Redis Lpush 命令
75.Redis Lpop 命令
76.Redis Llen 命令
77.Redis Linsert 命令
78.Redis Lindex 命令
79.Redis Brpoplpush 命令
80.Redis Brpop 命令
81.Redis Sdiff 命令
82.Redis Scard 命令
83.Redis Sadd 命令
84.Redis 集合(Set)
85.Redis Rpushx 命令
86.Redis Rpush 命令
87.Redis Rpoplpush 命令
88.Redis Rpop 命令
89.Redis Ltrim 命令
90.Redis Lset 命令
91.Redis Sunion 命令
92.Redis Srem 命令
93.Redis Srandmember 命令
94.Redis Spop 命令
95.Redis Smove 命令
96.Redis Smembers 命令
97.Redis Sismember 命令
98.Redis Sinterstore 命令
99.Redis Sinter 命令
100.Redis Sdiffstore 命令