wget http://download.redis.io/redis-stable.tar.gz
tar xzf redis-stable.tar.gz
cd redis-stable
make
# 将可执行程序复制到/usr/local/bin目录中以便以后执行程序时可以不用输入完整的路径
make install
# 测试Redis是否编译正确
make test
使用 make test
命令时提示 You need tcl 8.5 or newer in order to run the Redis test
,解决方案如下:
wget http://downloads.sourceforge.net/tcl/tcl8.6.1-src.tar.gz
tar xzvf tcl8.6.1-src.tar.gz -C /usr/local/
cd /usr/local/tcl8.6.1/unix/
./configure
make
make install
启动/停止
直接启动
redis-server
# Redis服务器默认使用6379端口,通过--port参数可以自定义端口号
redis-server --port 6380
初始化脚本启动 Redis
(推荐使用)
Redis
源代码目录下的 utils
文件夹中的 redis_init_script
这个初始化脚本文件复制到 /etc/init.d
目录下,取名为 redis_6379
,端口号可以改成自己想要的,只需修改脚本第6行 redisport
变量的值为同样的端口号即可/etc/redis
和 /var/redis/6379
,前者存放 Redis
的配置文件,后者存放 Redis
的持久化文件Redis
源代码目录下的 redis.conf
复制到 /etc/redis
目录中,以端口号命名(如 6379.conf
)。然后将配置项如下表修改daemonize yes 使Redis以守护进程模式运行
pidfile /var/run/redis_6379.pid 设置Redis的PID文件位置
port 6379 设置Reids监听的端口号
dir /var/redis/6379 设置持久化文件存放位置
现在就可以使用 /etc/init.d/redis_6379 start
来启动 Redis
了
Redis
redis-cli SHUTDOWN
入门
Redis
不区分命令大小写,但和 Mysql
一样,建议使用大写字母表示命令
# 列出符合表达式的键名列表,pattern支持glob风格通配符格式
KEYS pattern
SET bar 1
取出键为 "bar" 的值GET bar
判断一个键是否存在。存在返回1,否则返回0EXISTS key
删除键。可以一次删除多个键,返回删除的键个数DEL key [key ...]
删除所有符合规则的键redis-cli KEYS "sc_*" xargs redis-cli DEL
获得键值的数据类型TYPE key
符号 含义
------
? 匹配一个字符
* 匹配任意个(包含0个)字符
[] 匹配括号间的任一符号,可以使用 "-" 符号表示一个范围,如[a-c]可以匹配"a","b","c"
\x 匹配字符x,用于转义符号。如要匹配 "?" ,就需要使用 \?
- 字符串类型:`Redis` 最基本的数据类型,可以存储二进制数据、`JSON` 化的对象(比如图片),一个字符串类型的键允许存储数据的最大容量为512M。
> 常用命令
增加指定的整数,key为键,increment为增加的步进值
INCRBY key increment
减少指定的整数,参数同INCRBYDECRBY key increment
增加指定浮点数,参数同INCRBYINCRBYFLOAT key incremnet
向尾部追加值,key为键,value为追加的值。如果键不存在则将该键的值设置为value。返回值是追加后字符串的总长度APPEND key value
获取字符串长度,对于中文UTF-8编码,每一个中文长度是3STRLEN key
同事获得/设置多个键值MGET key [key ...]
MSET key value [key value ...]
- 散列类型
散列类型适合存储对象:使用对象类别和 `ID` 构成键名,使用字段表示对象的属性,而字段值则存储属性值,如下图所示。
graph LR
car:1-->color
car:1-->name
car:1-->price
color-->白色
name-->路虎
price-->90万
> 常用命令
散列类型的操作前缀带H
单个赋值
HSET key field value
单个取值HGET key
多个赋值HMSET key field value [field value ...]
多个取值HMGET key field [field ...]
取全部值HGETALL key
判断field字段是否存在HEXISTS key field
当field字段不存在时赋值HSETNX key field value
增加数字,如果key不存在则会自动建立并默认field字段为0,散列类型没有HINCR命令HINCRBY key field incremnet
删除field字段HDEL key field [field ...]
获取字段名/值HKEYS key
HVALS key
HLEN key
`HSET` 命令不区分插入和更新操作。当执行的是插入操作 `HSET` 返回 1,执行的是更新操作 `HSET` 返回 0
- 列表类型
> 常用命令
# 向列表两端增加元素
# 补充说明:当添加多个值时
# eg. LPUSH news n1 n2 n3
# 先将n1增加到news列表中,然后是n2,n3,所以最后news:[n3 n2 n1 ...],因此当使用LRANGE输出全部值时就会变成n3在最开始
LPUSH key value [value ...]
RPUSH key value [value ...]
# 向列表两端弹出元素
LPOP key
RPOP key
# 获取列表中元素的个数
LLEN key
# 获得列表片段,返回索引从start到stop之间的所有元素(包括两端的元素),也支持负索引
# 补充说明:
# 1. 如果start的索引位置比stop的索引位置靠后,则会返回空列表
# 2. 如果stop大于实际的索引范围,则会返回到列表最右边的元素
LRANGE key start stop
# eg.返回列表mylist中的所有元素
LRANGE mylist 0 -1
# 删除列表中指定的值,删除列表中前count个值为value的元素,返回值是实际删除的元素个数
# 补充说明:
# 1. 当 count > 0 时,LREM会从列表左边开始删除
# 2. 当 count < 0 时,LREM会从列表右边开始删除
# 3. 当 count = 0 时,LREM会删除所有值为value的元素
LREM key count value
# 获得/设置指定索引的元素值
LINDEX key index
LSET key index value
# 只保留列表指定片段
LTRIM key start end
# 补充说明:
# LTRIM常和LPUSH一起使用来限制列表中元素的数量,比如记录日志时只保留最近的100条日志
LPUSH logs newlog
LTRIM logs 0 99
# 向列表中插入元素,首先从左到右查找值为value1的元素,然后根据BEFORE或AFTER来决定将value2插入到该元素的前或后
LINSERT key BEFOREAFTER value1 value2
# 将一个列表右边的元素转到另一个列表左边
RPOPLPUSH source destination
```
集合类型
常用命令
# 增加/删除元素
# 补充说明:添加时若不存在该键则会自动创建。因为在集合中不能有相同的元素,所以如果元素已存在则会忽略。返回值时成功加入的元素数量
SADD key member [member ...]
SREM key member [member ...]
# 获得所有元素
SMEMBERS key
# 判断元素是否在集合中
SISMEMBER key member
# 集合间运算:差集、交集、并集
SDIFF key [key ...]
SINTER key [key ...]
SUNION key [key ...]
# 获得元素个数
SCARD key
# 进行集合运算并将结果存储,将运算的结果存储在destination键中,常用于多步集合运算的场景中
SDIFFSTORE destination key [key ...]
SINTERSTORE destination key [key ...]
SUNIONSTORE destination key [key ...]
# 随机获得集合中的元素
# 补充说明:
# 1. 当 count > 0 时,随机从集合中获得count个不重复的元素,如果count的值大于集合中的元素个数,则返回全部元素
# 2. 当 count < 0 时,随机从集合里获得count个有可能重复的元素
SRANDMEMBER key [count]
有序集合类型
常用命令
# 增加元素,如果元素已经存在则会用新的分数替换原有的分数,返回值时新价格的元素个数,分数不仅可以是整数,还支持双精度浮点数
# eg.
# -inf 表示负无穷 +inf 表示正无穷
# ZADD test -inf a
# ZADD test +inf b
ZADD key score member [score member ...]
# 获得元素的分数
ZSCORE key member
# 获得排名在某个范围的元素列表,可选参数 WITHSCORES 表示连带分数也一起输出
ZRANGE key start stop [WITHSCORES]
ZREVRANGE key start stop [WITHSCORES]
# 获得指定分数范围的元素
ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]
# 补充说明:
# 1. 如果希望分数范围不包含端点值,可以再分数前加上 “(” 符号。eg. ZRANGEBYSCORE test 60 (100
# 2. min 和 max 支持无穷大(-inf +inf)。eg. ZRANGEBYSCORE test (60 +inf
# 3. LIMIT offset count 与SQL中的用法基本相同
# 增加/减少某个元素的分数,返回值是更改后的分数
# eg. 给Jerry加4分:ZINCRBY test 4 Jerry
# eg. 给Jerry减4分:ZINCRBY test -4 Jerry
ZINCRBY key incremnet member
# 获得集合中元素的数量
ZCARD key
# 获得指定分数范围内的元素个数,min max同样支持无穷大
ZCOUNT key min max
# 按照排名范围删除元素,返回删除的元素数量
ZREMRANGEBYRANK key start stop
# 按照分数范围删除元素,返回删除的元素数量
ZREMRANGEBYSCORE key min max
# 获得元素的排名
ZRANK key member
ZREVRANK key member
# 计算有序集合的交集,destinade键中元素的分数是由AGGREGATE参数决定的
# 1. 当AGGREGATE时SUM(也就是默认值),destination键中元素的分数是每个参与计算的集合中该元素分数的和
# 2. 当AGGREGATE时MIN,destination键中元素的分数是每个参与计算的集合中最小的元素分数
# 3. 当AGGREGATE时MAX,destination键中元素的分数是每个参与计算的集合中最大的元素分数
# eg.
# ZADD ss1 1 a 2 b
# ZADD ss2 9 a 8 b
# ZINTERSTORE res 2 ss1 ss2 AGGREGATE SUM
# ZRANGE res 0 -1 WITHSCORES
# 结果:a 10 b 10
# 4. WEIGHTS参数可以设置每个集合的权重,在参与计算时元素的分数会被乘上该集合的权重
# eg,
# ZINTERSTORE res1 2 ss1 ss2 WEIGHTS 0.8 0.5
# 结果:a 8 b 5
ZINTERSTORE destination numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE SUMMINMAX]
Redis
中的事务是一组命令的集合,同命令一样都是 Redis
的最小执行单位,一个事务中的命令要么都执行,要么多不执行。
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
首先使用 MULTI
命令告诉 Redis
下列的命令是属于同一个事务的;接下来执行的所有命令返回 QUEUED
表示已经进入等待执行的事务队列中;使用 EXEC
告诉 Redis
将等待执行的事务队列中的所有命令按照发送顺序依次执行。如果在发送 EXEC
命令前客户端断线,则 Redis
会清空事务队列
EXEC
后 Redis
就会直接返回错误,其他正确的命令也不会执行Redis
不支持回滚功能,也使得 Redis
在事务上可以保持简洁和快速。上述两种错误,语法错误完全可以在开发时找出并解决,运行错误可以通过良好的规划数据库来规避# 监控一个或多个键,一旦其中有一个键被修改,之后的第一个事务就不会执行。监控一直持续到 EXEC 命令(因为事务中的命令是在 EXEC 之后才执行的,所以在 MULTI 命令之后 EXEC 命令之前是有可以修改监控的键的值),执行 EXEC 命令后会取消对所有键的监控
WATCH key [key ...]
# 取消监控,保证下一个事务的执行不会受到影响
UNWATCH key [key ...]
# 举例一:开始监听name后,在执行第一个事务前对name赋值,导致该事务不会执行,而第二个事务正常执行。也因此由于监控键的值在事务执行前被修改而导致失败后仍需再次执行,保证该事务的业务逻辑操作得到执行
redis> SET name koro
OK
redis> WATCH name
OK
redis> SET name sara
OK
redis> MULTI
OK
redis> SET name mike
QUEUED
redis> EXEC
(nil)
redis> GET name
"sara"
redis> MULTI
OK
redis> SET name lara
QUEUED
redis> EXEC
1) OK
redis> GET name
"lara"
生存时间:在 Redis
中可以使用 EXPIRE
命令设置一个键的生存时间,到时间后 Redis
会自动删除它
# 前者时间单位为秒,后者时间单位为毫秒。返回1表示设置成功,返回0表示键不存在或设置失败
EXPIRE key seconds
PEXPIRE key millisecond
# 查看指定键剩余生存时间(单位秒),返回-1表示键不存在或永久存在(设置一个键时默认为永久存在)
TTL key
# 取消键的生存时间设置,即将键恢复成永久的。返回1表示成功清除,返回0表示键不存在或已经是永久的
# 特别说明:使用 SET 或 GETSET 命令为键赋值也会同时清除键的生存时间;如果使用 WATCH 命令检测了一个拥有生存时间的键,该键时间到期自动删除并不会被 WATCH 命令认为该键被改变
PERSIST key
Redis
占满内存;另一方面如果为了防止 Redis
占用内存过大而将缓存键的生存时间设得太短,就可能导致缓存命中率过低并且大量内存白白地闲置。实际开发中会发现很难为缓存键设置合理的生存时间,为此可以闲置 Redis
能够使用的最大内存,并让 Redis
按照一定的规则淘汰不需要的缓存键,这种方式在只将 Redis
用作缓存系统时非常实用。maxmemory
参数,限制 Redis
最大可用内存大小(单位是字节),当超出了这个限制时 Redis
会依据 maxmemory-policy
参数指定的策略来删除不需要的键,直到 Redis
占用的内存小于指定内存。volatile-lru 使用LRU(最近最少)算法删除一个键(只对设置了生存时间的键)
allkeys-lru 使用LRU(最近最少)算法删除一个键
volatile-random 随机删除一个键(只对设置了生存时间的键)
allkeys-random 随机删除一个键
volatile-ttl 删除生存时间最近的一个键
noeviction 不删除键,只返回错误
排序
SORT
命令:可以对列表类型、集合类型和有序集合类型键进行排序,并且可以完成与关系数据库中的连接查询相类似的任务
ALPHA
参数DESC
参数LIMIT
参数:LIMIT offset count
(跳过前 offset
个元素并获取之后的 count
个元素)SORT tag:php:articles DESC LIMIT 1 2
BY
参数
BY 参考键
,其中参考键可以使字符串类型键或者是散列类型键的某个字段。如果提供了 BY
参数,SORT
命令将依据参考键的值来排序SORT tag:php:articles BY article:*->time DESC
SORT articles BY articles:* DESC
GET
参数
SORT
命令的返回结果不再是元素自身的值,而是 GET
参数中指定的键值。支持字符串类型和散列类型的键,并使用 *
作为占位符。可以有多个 GET
参数ID
对应的文章标题):SORT tag:php:articles BY article:*->time DESC GET article:*->title
GET #
可以获取元素本身的值STORE
参数
LIMIT
参数值获取需要的数据STORE
参数将结果缓存任务队列
当页面需要进行如发送邮件、复杂数据运算等耗时较长的操作时会阻塞页面的渲染。为了避免用户等待太久,应该使用独立的线程来完成这类操作。不过一些编程语言或框架不易实现多线程,这时就可以通过其他进程来实现,那么只需要通知这个进程向指定的地址发送邮件就可以了。
通知的过程可以借助任务队列来实现。与任务队列进行交互的实体有两类:生产者(producer)和消费者(consumer)。生产者会将需要处理的任务放入任务队列中,而消费者则不断从任务队列中读入任务信息并执行
好处:
loop
$task = BRPOP queue 0
execute $task[1]
命令:BRPOP
、BLPOP
说明:当列表中没有元素时会一直阻塞住连接,直到有新元素加入,才会从队列中弹出一个元素。
参数:key timeout
,第一个是键名,第二个是超时时间,单位是秒。当超过了此时间仍然没有获得新元素的话就会返回 nil
。若为 0,表示不限制等待的时间,即一直会等待新元素加入。
详解:
BLPOP key [key ...] timeout
优先级队列
当需要对通知给同一个进程的不同任务进行优先级对待的时候,可以使用完整格式的 BLPOP
来实现
“发布/订阅”模式:用到时再做分析
管道
通过管道可以一次性发送多条命令并在执行完后一次性将结果返回。管道通过减少客户端与 Redis
的通信次数来实现降低往返时延累计值的目的
very.important.person:20
改成 VIP:20
,将存储用户性别的字符串类型键的值改成 0 和 1。phpredis
Redis
phpize
./configure [--enable-redis-igbinary]
make && make install
php-redis
扩展。修改你的 php.ini
文件或者在 /etc/php5/conf.d
中添加一个 redis.ini
文件,内容为 extension=redis.so
Redis
在2.6版推出了脚本功能,允许开发者使用 Lua
语言编写脚本传到 Redis
中执行。在 Lua
脚本中可以调用大部分人的 Redis
命令。Redis
会将整个脚本作为一个整体执行,中间不会被其他命令插入。也就是说在编写脚本的过程中无需担心会出现竞态条件,也就无需使用事务。事务可以完成的所有功能都可以用脚本来实现。Redis
中,这就意味着其他客户端(可以使其他语言开发的项目)可以复用这一脚本而不需要使用代码完成同样的逻辑。Lua
代码local times = redis.call('incr', KEYS[1])
if times == 1 then
-- 如果KEYS[1]刚创建,为其设置生存时间
redis.call('expires', KEYS[1], ARGV[1])
end
if times > tonumber(ARGV[2]) then
return 0
end
return 1
redis-cli --eval ./ratelimiting.lua rate.limiting:127.0.0.1 , 10 3
参数说明:
--eval
是告诉redis-cli
读取并运行后面的Lua
脚本,./ratelimiting.lua
是指脚本文件的位置,后面跟着脚本的参数,其中,
前的参数是要操作的键,在脚本中KEYS[1]
获取,,
后的参数是使用ARGV[1]
和ARGV[2]
获得。特别的,,
两边的空格不能省略,否则会出错。
Redis
与 Lua
在脚本中调用 Redis
命令:redis.call()
整数 数字
字符串 字符串
多行字符串 表(数组形式)
状态 表(只有一个ok字段存储状态信息)
错误 表(只有一个err字段存储状态信息)
EVAL
命令:Redis
提供了该命令使其可以像调用其他内置命令一样调用脚本。
EVAL script key_count [key ...] [arg ...]
script
表示脚本的内容,key_count
表示key参数的个数,这样才能确定后面的哪几个是key,哪几个是arg,特别的,当脚本不需要任何参数时也不能省略 key_count
这个参数EVALSHA
命令:如果每次调用脚本都需要将整个脚本传给 Redis
会占用较多的带宽。所以提供该命令允许开发者通过脚本内容的 SHA1
摘要来执行脚本。与 EVAL
命令基本相同,只不过将脚本内容换成脚本内容的 SHA1
摘要。
Redis
客户端都会代替开发者完成这一流程):
SHA1
摘要,并使用 EVALSHA
命令执行脚本。NOSCRIPT
错误则使用 EVAL
命令重新执行脚本。实例:
$script = 'return redis.call("set", "test", "aaa")';
if (($sha = $this->redis->script('load', $script)) !== false) {
$this->redis->evalSha($sha);
}
echo $this->redis->get("test");
原子性和执行时间:脚本执行期间 Redis
不会执行其他命令。为了防止某个脚本执行时间过长导致 Redis
无法提供服务(比如陷入死循环),Redis
提供了 lua-time-limit
参数限制脚本的最长运行时间,默认为5秒。如果超过这一限制后,Redis
将开始接收其他命令但不会执行(以确保脚本的原子性,因为此时脚本并没有终止),但是会返回 BUSY
错误。特别地,如果执行的脚本对数据进行了修改,那么 SCRIPT KILL
命令不会终止脚本的运行(因为如果脚本执行了一部分就被终止,会违背脚本的原子性要求)。这时只能通过 SHUTDOWN NOSAVE
命令强行终止。而改命令不会进行持久化操作,意味着所有发生在上一次快照后的修改都会丢失。
Redis
脚本非常高效,所以在大部分情况下都不用担心脚本的性能。但同时由于脚本的强大功能,很多原本在程序中执行的逻辑都可以放到脚本中执行,这时就需要开发者根据实际情况权衡到底哪些任务适合交给脚本。通常来讲不应该在脚本中进行大量耗时的计算。最后,
2024 - 快车库 - 我的知识库 重庆启连科技有限公司 渝ICP备16002641号-10
企客连连 表单助手 企服开发 榜单123