赋值与取值
SET key value
GET key
递增数字
INCR key
增加指定的整数
INCRBY key increment
减少指定的整数
DECR key
DECRBY key decrement
增加指定的浮点数
INCRBYFLOAT key incrment
向尾部追加值
APPEND key value
获取字符串的长度
STRLEN key
同时获取、设置多个键值
MGET key [key...]
MSET key value [key value...]
位操作
GETBIT key offset
SETBIT key offset value
--获取字符串中值是1的个数
BITCOUNT key [start] [end]
--位运算
BITOP operation destkey key [key...]
赋值与取值
HSET key field value
HGET key field
HMSET key field value [field value...]
HMGET key field [field...]
HGETALL key
判断字段是否存在
HEXISTS key field
字段不存在时赋值
HSETNX key field value
增加数字
HINCRBY key field incrment
删除字段
HDEL key field [field...]
只获得字段名或字段值
HKEYS key
HVALS key
获得字段数量
HLEN key
向列表两端增加元素
LPUSH key value [value...]
RPUSH key value [value...]
从列表两端弹出元素
LPOP key
RPOP key
获取列表中元素个数
LLEN key
获取列表片段
LRANGE key start stop
删除列表中指定值
--删除列表中前count个值value
LREM key count value
获得、设置指定索引的元素值
LINDEX key index
LSET key index value
只保留列表指定片段
LTRIM key start end
向列表中插入元素
--首先从左到右找到值为pivot的元素
LINSERT key BEFORE|AFTER pivot value
将元素从一个列表转到另一个列表
整个过程是原子的
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
进行集合运算并将结果存储
SDIFFSTORE destination key [key...]
SINTERSTORE destination key [key...]
SUNIONSTORE destination key [key...]
随机获取集合中的元素
SRANDOMMEMBER key [count]
count为负数时,获取|count|个元素,有可能重复
从集合中弹出一个元素
SPOP key
增加元素
ZADD key score member [score member...]
获得元素分数
ZSCORE key member
获得排名在某个范围的元素列表
从小到大
ZRANGE key start stop [WITHSCORES]
从大到小
ZREVRANGE key start stop [WITHSCORES]
获得指定分数范围的元素
ZRANGEBYSCORE key min max [WITHSCORE] [LIMIT offset count]
ZREVRANGEBYSCORE key max min [WITHSCORE] [LIMIT offset count]
增加某个元素的分数
ZINCRBY key increment member
获得集合中元素的数量
ZCARD key
获取指定分数范围内的元素个数
ZCOUNT key min max
删除一个或多个元素
ZREM key member [member...]
按分数范围删除元素
ZREMRANGEBYSCORE key min max
获得元素的排名
ZRANK key member
ZREVRANK key member
计算有序集合的交集
ZINTERSTORE destination numkeys key [key...] [WEIGHTS weight [weight...]] [AGGREGATE SUM|MIN|MAX]
Redis中的事务是一组命令的集合,要么全执行,要么全部不执行
MULTI
...
EXEC
语法错误:命令不存在或命令参数不对
运行错误:如使用散列类型的命令操作集合类型的键
watch命令可以监控一个或多个键,一旦其中有一个键被修改或删除,之后的事务不会执行
设置过期时间
以秒为单位
EXPIRE key seconds
以毫秒为单位
PEXPIRE key time
查看一个键还有多长时间会过期
TTL key
PTTL key
取消过期时间设置
PERSIST key
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UM1qx9yb-1600151506524)(evernotecid://74468EB7-42C7-45DB-866A-4E29E67D7A88/appyinxiangcom/30161773/ENResource/p219)]
SORT key
SORT key ALPHA
SORT key DESC
散列类型
SORT key BY item:*->field DESC
参考键还可以是字符串类型
LPUSH sortbylist 2 1 3
SET itemscore:1 50
SET itemscore:2 100
SORT sortlist BY itemscore:* DESC
GET参数不影响排序,它的作用是使SORT命令返回的结果不再是元素自身的值,而是GET参数中指定的键值
SORT key BY item:*->time DESC GET item:*->title GET item:*->time GET #
GET #会返回元素本身的值
结果保存在sort.result键中
SORT key BY item:*->time DESC GET item:*->title GET item:*->time GET # STORE sort.result
SORT命令的时间复杂度为O(n+mlog(m)),n为要排序的列表元素个数,m为要返回的元素个数
BPOP可以阻塞获取元素
BPOP queue 0
0表示不限制等待时间
优先级队列实现
如果有多个键,按照从左到右顺序先取第一个队列中的元素
BPOP queue:1 queue:2 queue:3 0
发布消息
PUBLISH channel.1 message
订阅消息
SUBSCRIBE channel.1
处于订阅状态下客户端不能使用除SUBSCRIBE、UNSUBSCRIBE、PSUBSCRIBE、PUNSUBSCRIBE这四个属于发布订阅模式的命令之外的命令,否则会报错
订阅返回数据
规则支持glob风格的通配符格式
PSUBSCRIBE channel.?*
Redis的底层通信协议对管道提供了支持,通过管道可以一次性发送多条命令并在执行完后一次返回结果,当一组命令中每条命令都不依赖之前命令的返回值时,可以通过管道来发送减少通信次数
OBJECT ENCODING key
Redis 每个键值都使用一个redisObject结构体保存
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mCrtNQKB-1600151506532)(evernotecid://74468EB7-42C7-45DB-866A-4E29E67D7A88/appyinxiangcom/30161773/ENResource/p220)]
其中type表示数据类型,取值如下
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-U5pvE5ao-1600151506535)(evernotecid://74468EB7-42C7-45DB-866A-4E29E67D7A88/appyinxiangcom/30161773/ENResource/p221)]
encoding 表示Redis键值的内部编码方式
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FKZ6tHrQ-1600151506537)(evernotecid://74468EB7-42C7-45DB-866A-4E29E67D7A88/appyinxiangcom/30161773/ENResource/p222)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tp93ZeUX-1600151506539)(evernotecid://74468EB7-42C7-45DB-866A-4E29E67D7A88/appyinxiangcom/30161773/ENResource/p223)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TPpjnHB1-1600151506541)(evernotecid://74468EB7-42C7-45DB-866A-4E29E67D7A88/appyinxiangcom/30161773/ENResource/p224)]
散列类型键的字段个数少于entries参数值且每个字段名和字段值得长度都小于value参数值时,使用ZIPLIST来存储该键节省空间
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gDDAMKpT-1600151506542)(evernotecid://74468EB7-42C7-45DB-866A-4E29E67D7A88/appyinxiangcom/30161773/ENResource/p225)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jQF48xTd-1600151506542)(evernotecid://74468EB7-42C7-45DB-866A-4E29E67D7A88/appyinxiangcom/30161773/ENResource/p226)]
当集合中的所有元素都是整数且元素个数小于配置set-max-intset-entries值(默认512)时,Redis会使用REDIS_ENCODING_INTSET
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Fw1XE9Ep-1600151506543)(evernotecid://74468EB7-42C7-45DB-866A-4E29E67D7A88/appyinxiangcom/30161773/ENResource/p227)]
使用SKIPLIST时,Redis使用散列表和跳跃列表两种数据结构来存储,散列表用来存储元素值与元素分数的映射实现O(1)的ZSCORE等命令,跳跃表用来存储元素的分数及其元素值得映射实现排序的功能
ZIPLIST按“元素1,元素1分数,元素2,元素2分数…“并且分数是有序的
redis允许开发者使用Lua语言编写脚本传到Redis执行,在Lua脚本中可以调用大部分Redis命令
local c 默认为nil
存储函数的局部变量
local say = function ()
print 'hi'
end
变量名必须是非数字开头,只能包含字母、数字、下划线、区分大小写,不能与Lua关键字相同
保留关键字如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1ilgCJhI-1600151506544)(evernotecid://74468EB7-42C7-45DB-866A-4E29E67D7A88/appyinxiangcom/30161773/ENResource/p230)]
单行注释
-- 到行尾
多行注释
--[[
...
]]
支持多重赋值
local a, b = 1, 2
local a, b, c = 1, 2, 3 --3被舍弃了
local a, b = 1 --b是nil
计算多重赋值时,会先计算所有表达式的值
数学操作符:+、-、*、/、%、-(取负)、幂运算函数^
比较操作符
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-v6CQB21Y-1600151506545)(evernotecid://74468EB7-42C7-45DB-866A-4E29E67D7A88/appyinxiangcom/30161773/ENResource/p231)]
逻辑操作符
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-b0QDJs6b-1600151506545)(evernotecid://74468EB7-42C7-45DB-866A-4E29E67D7A88/appyinxiangcom/30161773/ENResource/p232)]
类型转换
tonumber('1')
tostring(1)
还可以进制转换
tonumber('F', 16) -- 将F从16进制转为十进制15
连接操作符
'hello' .. ' ' .. 'world'
取长度操作符,获取字符串或表的长度
print(#'hello')
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pVR9FmCs-1600151506546)(evernotecid://74468EB7-42C7-45DB-866A-4E29E67D7A88/appyinxiangcom/30161773/ENResource/p233)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1RpOvz2L-1600151506547)(evernotecid://74468EB7-42C7-45DB-866A-4E29E67D7A88/appyinxiangcom/30161773/ENResource/p234)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-b2YxckwC-1600151506548)(evernotecid://74468EB7-42C7-45DB-866A-4E29E67D7A88/appyinxiangcom/30161773/ENResource/p235)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QSXcL2E0-1600151506549)(evernotecid://74468EB7-42C7-45DB-866A-4E29E67D7A88/appyinxiangcom/30161773/ENResource/p236)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-m8iyJipQ-1600151506550)(evernotecid://74468EB7-42C7-45DB-866A-4E29E67D7A88/appyinxiangcom/30161773/ENResource/p237)]
pairs和ipairs的区别是前者会遍历所有值不为nil的索引,而后者只会从索引1开始递增遍历到最后一个不为nil的整数索引
function (参数列表)
函数体
end
可变参数使用 …
return unpack(argv)返回多个值
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cyWHYSil-1600151506550)(evernotecid://74468EB7-42C7-45DB-866A-4E29E67D7A88/appyinxiangcom/30161773/ENResource/p238)]
获取字符串长度
string.len(string)
#'helllo'
转换大小写
string.lower('cfsd')
string.upper()
获取子字符串
string.sub(string,start [, end])
将数组转换为字符串
-- 中间以sep分割,i和j限制索引范围
table.concat(table [, sep [, i[, j]]])
向数组中插入元素
-- pos默认为数组长度+1
table.insert(table, [pos,] value)
从数组中弹出一个元素
table.remove(table [, pos])
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-o8kyxbbA-1600151506551)(evernotecid://74468EB7-42C7-45DB-866A-4E29E67D7A88/appyinxiangcom/30161773/ENResource/p239)]
math.random([m, [, n]])
math.randomseed(x)
随机数依据种子(seed)计算的伪随机数,同一种子的随机序列相同
Redis通过cjson和cmsgpack提供了对JSON和MessagePack的支持,Redis自动加载了这两个库
使用cjson序列化成字符串
local jason_people = cjson.encode(people)
使用cmsgpack序列化成字符串
local people_str = cmsgpack.pack(people)
将字符串反序列化成表
local json_people_obj = cjson.decode(people)
local people_obj = cmsgpack.unpack(people)
redis.call('set', 'foo', 'bar')
local value = redis.call('get', 'foo')
Redis还提供了redis.pcall()函数,与redis.call的区别是pcall执行出错时会记录错误继续执行,而call直接返回错误,不会继续执行
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-R2hHeMrx-1600151506552)(evernotecid://74468EB7-42C7-45DB-866A-4E29E67D7A88/appyinxiangcom/30161773/ENResource/p240)]
EVAL命令
-- 脚本不需要任何参数时也不能省略key参数数量0
EVAL 脚本内容 key参数数量 [key ...] [value ...]
EVALSHA命令
是对脚本命令进行缓冲,减少带宽占用
Redis默认将快照文件存储在工作目录中的dump.rdb中,可以通过配置dir和dbfilename两个参数指定路径和文件名
执行快照的几种情况
-- 900秒内有一个或一个以上键被更改则进行快照
save 900 1
默认Redis没有开启AOF持久化,通过appendonly参数启用,AOF文件的保存位置和RDB相同,通过dir和appendfilename参数修改
由于操作系统的缓存机制,数据并没有真正的写入硬盘,而是进入了系统的硬盘缓存,默认情况下系统每30秒执行一次同步操作,此时如果系统异常会丢失30秒的内容
Redis在写入AOF文件后主动要求系统将缓存同步到硬盘中,可以通过appendfsync参数设置
复制(replication)功能,可以实现将数据在从库中备份
在从数据库的配置文件中加入如下,主数据库无需任何配置
slaveof 主数据地址 主数据库端口
redis-server
redis-server --port 6380 --slaveof 127.0.0.1 6379
还可以在运行时通过命令更改主服务器
SLAVEOF 127.0.0.1 6379
主数据崩溃,手动恢复
主数据库关闭持久化,一定不能自动重启,不然会清空所有从数据库
主从复制时使用RDB同步快照文件,存在如下缺点
从2.8.18版本开始支持无硬盘复制选项,直接通过网咯发送给从数据库
repi-diskless-sync yes
基于以下三点
执行增量复制
哨兵用于监控Redis的运行状况
配置哨兵,建立一个配置文件,其中mymaster表示要监控的主数据库名字,可以自己定义,1表示最低通过票数
sentinel monitor mymaster 127.0.0.1 6379 1
启动Sentinel进程
$ redis-sentinel /path/to/sentinel.conf
哨兵启动后,会与要监控的主数据库建立两条连接,一条用来订阅,一条用来发送命令
哨兵会定时执行下面的3个操作
选举领头哨兵(raft)
故障恢复
相对稳妥的部署方案
CLUSTER MEET ip port
ip和port是集群中任一节点,就可以完成加入整个集群
根据有效键计算分配给16384个插槽
添加一个新节点
第一次访问任一节点,检查是否在本节点中,如果不在返回一个错误信息(键所在的节点),重新发送请求,可以在客户端缓存所有的插槽路由信息优化
发现故障
节点恢复
可信环境
数据库密码
通过配置文件中的requirepass参数设置密码
发送密码用AUTH命令
AUTH 密码
Redis密码输入错误后并不会主动延迟,所以攻击者可以通过穷举法破解Redis密码(1秒可以尝试十几万个)
重命名命令
配置文件中
rename-command 命令 新命令
禁用命令
rename-command 命令 “”
保证配置文件的安全性,否则没有意义
简单协议
简单的以空格分开,无法输入二进制字符
Redis返回格式
统一请求协议
命令格式和多行字符串回复的格式很类似,命令指定了后面字符串的长度,可以包含二进制字符
-- set foo bar
*3
$3
SET
$3
foo
$3
bar
+OK
Redis的AOF文件和主从复制时主数据库向从数据库发送的内容都使用了统一请求协议,开发一个和Redis直接通信的客户端可以使用此协议
可通过配置slowlog-log-slower-than参数设置耗时限制,单位是微秒(1000000 微秒= 1秒),耗时命令日志存储在内存中,可以配置slowlog-max-len限制条数
SLOWLOG GET
每条日志由四部分组成
客户端可以监控Redis服务器的执行命令,但是消耗性能,适合用来调试
MONITOR