Redis

文章目录

    • Redis
      • Redis基本命令
        • 字符串
        • 散列
        • 列表
        • 集合
        • 有序集合
      • Redis事务
        • 错误处理
        • WATCH 命令
      • 过期时间
      • 排序
        • SORT 命令
        • BY 参数
        • GET 参数
        • STORE参数
        • 性能
      • 消息
        • 发布订阅
        • 按照规则订阅
      • 管道
      • 节省存储空间
        • 查看键的内部编码方式
        • String编码格式
        • HASH编码格式
        • 列表类型编码格式
        • 集合类型编码格式
        • 有序集合编码格式
      • 脚本
        • 变量
        • 注释
        • 赋值
        • 操作符
        • if语句
        • 循环语句
        • 表类型
        • 函数
      • 标准库
        • String库
        • Table库
        • Math库
      • 其它库
      • Redis与Lua
        • 脚本中调用redis命令
        • 脚本相关命令
      • 持久化
        • RDB方式
        • AOF方式
    • 集群
      • 复制
        • 配置
        • 原理
        • 从数据库持久化
        • 无硬盘复制
        • 增量复制(2.8及以后)
      • 哨兵
        • 实现原理
        • 哨兵的部署
      • 集群
        • 节点增加
        • 插槽的分配
        • 获取与插槽对应的节点
        • 故障恢复
      • 管理
        • 安全
        • 通信协议
      • 管理工具
        • 耗时命令日志
        • 命令监控

Redis

Redis基本命令

字符串

赋值与取值

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事务

Redis中的事务是一组命令的集合,要么全执行,要么全部不执行

MULTI
...
EXEC

错误处理

语法错误:命令不存在或命令参数不对

  1. 一个事务内只要有一个命令有语法错误,语法正确的命令也不会执行
  2. 2.6.5之前会忽略语法错误的命令,其它正确的可以执行

运行错误:如使用散列类型的命令操作集合类型的键

  1. 没有出现错误的命令会执行
  2. Redis的事务没有回滚功能

WATCH 命令

watch命令可以监控一个或多个键,一旦其中有一个键被修改或删除,之后的事务不会执行

  1. EXEC会取消对所有键的控制
  2. 也可以使用UNWATCH来取消监控
  3. 检测一个拥有过期时间的键,到期后自动删除不会被WATCH命令认为该键被改变

过期时间

  1. 对键值进行操作的命令如(INCR、LPUSH、HSET、ZREM)均不会影响键的过期时间
  2. seconds必须是整数

设置过期时间

以秒为单位
EXPIRE key seconds

以毫秒为单位
PEXPIRE key time

查看一个键还有多长时间会过期

TTL key

PTTL key
  1. TTL 键不存在时,返回-2
  2. 永久存在,TTL返回-1
  3. 2.6版本前,无论是不存在还是没有过期时间都是返回-1

取消过期时间设置

PERSIST key

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UM1qx9yb-1600151506524)(evernotecid://74468EB7-42C7-45DB-866A-4E29E67D7A88/appyinxiangcom/30161773/ENResource/p219)]

排序

SORT 命令

  1. sort可以对集合、列表、有序集合进行排序
  2. 可以通过ALPHA参数实现按照字典排序非数字元素
SORT key

SORT key ALPHA

SORT key DESC

BY 参数

散列类型

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 参数

GET参数不影响排序,它的作用是使SORT命令返回的结果不再是元素自身的值,而是GET参数中指定的键值

SORT key BY item:*->time DESC GET item:*->title GET item:*->time GET #

GET #会返回元素本身的值

STORE参数

结果保存在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为要返回的元素个数

  1. sort会建立临时表
  2. 尽可能减少排序键中元素的数量(使n尽可能小)
  3. 使用LIMIT参数只获取需要的数据(使m尽可能小)
  4. 如果要排序的数据数量较大,尽可能适应STORE参数将结果缓存

消息

BPOP可以阻塞获取元素

BPOP queue 0
0表示不限制等待时间

优先级队列实现

如果有多个键,按照从左到右顺序先取第一个队列中的元素
BPOP queue:1 queue:2 queue:3 0

发布订阅

发布消息

PUBLISH channel.1 message

订阅消息

SUBSCRIBE channel.1

处于订阅状态下客户端不能使用除SUBSCRIBE、UNSUBSCRIBE、PSUBSCRIBE、PUNSUBSCRIBE这四个属于发布订阅模式的命令之外的命令,否则会报错
订阅返回数据

  1. subscribe 表示订阅成功的返回消息,第二个值是订阅成功的频道名称,第三个值是当前客户端订阅的频道数量
  2. message 表示接收到消息,第二个值表示产生消息的频道,第三个值是消息的内容
  3. unsubscribe 表示成功取消订阅,第二个值是频道名称,第三个值是当前客户端订阅数量,值为0表示客户端会退出订阅状态,之后就可以执行其他命令了

按照规则订阅

规则支持glob风格的通配符格式

PSUBSCRIBE channel.?*

管道

Redis的底层通信协议对管道提供了支持,通过管道可以一次性发送多条命令并在执行完后一次返回结果,当一组命令中每条命令都不依赖之前命令的返回值时,可以通过管道来发送减少通信次数

节省存储空间

  1. 精简键名和键值
  2. 内部编码优化

查看键的内部编码方式

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)]

String编码格式

  1. REDIS-ENCODING-EMBSTR(3.0后)
  2. REDIS-ENCODING-RAW
    内容不超过39字节时,采用EMBSTR编码,进行修改操作后,会转换成RAW编码

HASH编码格式

  1. REDIS_ENCODING-HT
  2. REDIS_ENCODING_ZIPMAP

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(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)]

列表类型编码格式

  1. REDIS_ENCODING_LINKEDLIST
  2. REDIS_ENCODING_ZIPLIST
  3. REDIS_ENCODING_QUICKLIST(前两个的结合)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jQF48xTd-1600151506542)(evernotecid://74468EB7-42C7-45DB-866A-4E29E67D7A88/appyinxiangcom/30161773/ENResource/p226)]

集合类型编码格式

  1. REDIS_ENCODING_HT
  2. REDIS_ENCODING_INTSET

当集合中的所有元素都是整数且元素个数小于配置set-max-intset-entries值(默认512)时,Redis会使用REDIS_ENCODING_INTSET

有序集合编码格式

  1. REDIS_ENCODING_SKIPLIST
  2. REDIS_ENCODING_ZIPLIST

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(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命令

  1. 减少网络开销
  2. 原子操作
  3. 复用

变量

  1. 全局变量不用声明,只有nil和非nil
  2. Redis中不允许使用全局变量,避免脚本之间互相影响
  3. 声明局部变量为local
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)]

  1. 数学操作符会自动转换类型
  2. 比较操作符不会自动转换类型
  3. 操作数不是nil或false,逻辑操作符就认为是真

if语句

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(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库

获取字符串长度

string.len(string)
#'helllo'

转换大小写

string.lower('cfsd')
string.upper()

获取子字符串

string.sub(string,start [, end])

Table库

将数组转换为字符串

-- 中间以sep分割,i和j限制索引范围
table.concat(table [, sep [, i[, j]]])

向数组中插入元素

-- pos默认为数组长度+1
table.insert(table, [pos,] value)

从数组中弹出一个元素

table.remove(table [, pos])

Math库

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(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与Lua

脚本中调用redis命令

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命令
是对脚本命令进行缓冲,减少带宽占用

  1. 先计算脚本的SHA1摘要,并使用EVALSHA命令执行脚本
  2. 获得返回值,如果返回’NOSCRIPT‘错误则使用EVAL命令

持久化

RDB方式

Redis默认将快照文件存储在工作目录中的dump.rdb中,可以通过配置dir和dbfilename两个参数指定路径和文件名

  1. Redis使用fork函数复制一份当前进程的副本
  2. 父进程继续接收并处理命令,而子进程将内存中数据写入硬盘中的临时文件
  3. 当子进程写入完成会用临时文件替换旧的RDB文件
  4. 在fork的那一刻,接收的命令会复制一份,fork完之后替换

执行快照的几种情况

  1. 根据配置规则执行
  2. 用户执行SAVE或BGSAVE
  3. 执行FLUSHALL命令
  4. 执行复制(replication)时
-- 900秒内有一个或一个以上键被更改则进行快照
save 900 1

  1. 只要自动快照条件不为空,执行FLUSHALL操作就会进行快照
  2. 使用LASTSAVE查看最近一次成功执行快照时间

AOF方式

默认Redis没有开启AOF持久化,通过appendonly参数启用,AOF文件的保存位置和RDB相同,通过dir和appendfilename参数修改

  1. AOP可以自动重写,将冗余的命令删除
  2. 载入速度比RDB慢

由于操作系统的缓存机制,数据并没有真正的写入硬盘,而是进入了系统的硬盘缓存,默认情况下系统每30秒执行一次同步操作,此时如果系统异常会丢失30秒的内容
Redis在写入AOF文件后主动要求系统将缓存同步到硬盘中,可以通过appendfsync参数设置

集群

  1. 一个从数据库也可拥有从数据库

复制

复制(replication)功能,可以实现将数据在从库中备份

配置

在从数据库的配置文件中加入如下,主数据库无需任何配置

slaveof 主数据地址 主数据库端口

redis-server
redis-server --port 6380 --slaveof 127.0.0.1 6379

还可以在运行时通过命令更改主服务器

SLAVEOF 127.0.0.1 6379

原理

  1. 当一个从数据库启动后,向主数据库发送SYNC命令
  2. 主数据库开始在后台保存快照,并缓存快照期间的命令
  3. 快照完成后,主数据库将快照文件和缓存命令发给从数据库
  4. 复制初始化完成后,主数据每次写命令都会异步同步给从数据库

从数据库持久化

主数据崩溃,手动恢复

  1. 在从数据库中使用SLAVEOF NO ONE命令将从数据库提升为主数据库
  2. 启动之前崩溃的主数据库,然后使用SALVEOF命令将其设置成新主数据库的从数据库

主数据库关闭持久化,一定不能自动重启,不然会清空所有从数据库

无硬盘复制

主从复制时使用RDB同步快照文件,存在如下缺点

  1. 当主数据库禁用RDB快照时,如果执行了复制初始化操作,会产生RDB文件,下次启动后主数据库会以该快照恢复数据,此时RDB可能是很久以前的数据
  2. 复制初始化时需要在硬盘中创建RDB快照文件,性能很差

从2.8.18版本开始支持无硬盘复制选项,直接通过网咯发送给从数据库

repi-diskless-sync yes

增量复制(2.8及以后)

基于以下三点

  1. 从数据库会存储主数据库的运行ID
  2. 复制同步阶段,主数据库每将一个命令传送给从数据库时,都会同时把该命令存放到一个积压队列(backlog)中,并记录下当前积压队列中存放命令的偏移量
  3. 从数据库接收主数据库传来的命令时,会记录下该命令的偏移量

执行增量复制

  1. 主数据库判断从数据库传来的ID是否与自己的ID相同
  2. 然后判断从数据库最后同步成功的命令偏移量是否在积压队列中如果在则执行增量复制

哨兵

哨兵用于监控Redis的运行状况

  1. 监控主数据库和从数据库是否正常
  2. 主数据库出现故障时自动将从数据库转换为主数据库

配置哨兵,建立一个配置文件,其中mymaster表示要监控的主数据库名字,可以自己定义,1表示最低通过票数

sentinel monitor mymaster 127.0.0.1 6379 1

启动Sentinel进程

$ redis-sentinel /path/to/sentinel.conf

实现原理

哨兵启动后,会与要监控的主数据库建立两条连接,一条用来订阅,一条用来发送命令
哨兵会定时执行下面的3个操作

  1. 每10秒哨兵会向主数据库和从数据库发送INFO命令
  2. 每2秒哨兵会向主数据库和从数据库的_sentinel_":hello频道发送自己的信息
  3. 每1秒哨兵会向主数据库、从数据库和其它哨兵节点发送PING命令

选举领头哨兵(raft)

  1. 发现主数据库客观下线的哨兵节点A,向每个哨兵节点发送命令,要求对方选择自己成为领头哨兵
  2. 如果目标哨兵节点没有选过其它节点,则会同意将A设置为领头哨兵
  3. 如果A发现有超过半数的且超过quorum参数值的哨兵节点同意选自己成为领头哨兵,则A成功成为领头哨兵
  4. 当有多个哨兵节点同时参选领头哨兵,则会出现没有任何节点当选的可能,此时每个参选节点将等待一个随机时间重新发起参选请求,进行下一轮选举

故障恢复

  1. 选择优先级最高的从数据库,优先级可以通过slave_priority选项来设置
  2. 如果有多个最高优先级的从数据库,则复制的命令偏移量越大越优先
  3. 如果以上条件都一样,则选择运行ID较小的从数据库
  4. 领头哨兵向数据库发送SLAVEOF NO ONE 命令使其升为主数据库
  5. 向其他从数据库发送SLAVEOF使其成为新主数据库的从数据库

哨兵的部署

相对稳妥的部署方案

  1. 为每个节点部署一个哨兵
  2. 使每个哨兵与其对应的节点的网络环境相同或相近

集群

节点增加

CLUSTER MEET ip port

ip和port是集群中任一节点,就可以完成加入整个集群

插槽的分配

根据有效键计算分配给16384个插槽
添加一个新节点

  1. 在新节点执行CLUSTER SETSLOT 插槽号 IMPORTING 旧节点运行ID
  2. 在旧节点执行CLUSTER SETSLOT 插槽号 MIGRATING 新节点运行ID
  3. 执行CLUSTER GETKEYSINSLOT 插槽号 获取键列表
  4. 对第三步获取的每个键执行MIGRATE命令,将其迁移到新节点中
  5. 执行CLUATER SETSLOT 插槽号 NODE 新节点ID

获取与插槽对应的节点

第一次访问任一节点,检查是否在本节点中,如果不在返回一个错误信息(键所在的节点),重新发送请求,可以在客户端缓存所有的插槽路由信息优化

故障恢复

发现故障

  1. 一旦节点A认为节点B疑似下线,就会在集群中传播消息
  2. 当集群中的节点C收集到半数以上的节点认为B是疑似下线时,就会将B标记为下线,并向集群传播消息

节点恢复

  1. 发现其复制的主数据库下线的从数据库(A)向集群中的每个节点发送请求,要求选择自己成为主数据库
  2. 如果请求的节点没有选过其它节点,则会同意A设置成主数据库
  3. 如果A发现有超过集群中节点总数一半的节点同意选自己,则A成为主数据库
  4. 当有多个从数据库节点同时参选主数据库,则会出现没有任何节点当选的可能,此时每个参选节点将等待一个随机事件重新发送参选请求,进行下一轮选举

管理

安全

可信环境

  1. 生产环境下不允许外界直接连接到Redis服务器,只能通过应用程序进行中转
  2. 在配置文件中修改bind参数,只允许本机应用连接Redis
  3. bind参数只能绑定一个地址,想更自由的设置可通过防火墙来完成

数据库密码
通过配置文件中的requirepass参数设置密码

发送密码用AUTH命令

AUTH 密码

Redis密码输入错误后并不会主动延迟,所以攻击者可以通过穷举法破解Redis密码(1秒可以尝试十几万个)

重命名命令

配置文件中
rename-command 命令 新命令

禁用命令
rename-command 命令 “”

保证配置文件的安全性,否则没有意义

通信协议

简单协议
简单的以空格分开,无法输入二进制字符
Redis返回格式

  1. 错误回复以-开头,并在后面跟上错误信息,以\r\n结尾
  2. 状态回复以+开头,并在后面跟上状态信息,以\r\n结尾
  3. 整数回复以:开头,并在后面跟上数字,以\r\n结尾
  4. 字符串以$开头,并在后面跟上字符串长度,接着是字符串的内容并以\r\n分割
  5. 多行字符串回复以*开头,并在后面跟上字符串回复的数组,并以\r\n分割,接着后面跟的就是字符串回复的具体内容了

统一请求协议
命令格式和多行字符串回复的格式很类似,命令指定了后面字符串的长度,可以包含二进制字符

-- 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

每条日志由四部分组成

  1. 该日志唯一ID
  2. 该命令执行的Unix时间
  3. 该命令的耗时时间,单位是微秒
  4. 命令及参数

命令监控

客户端可以监控Redis服务器的执行命令,但是消耗性能,适合用来调试

MONITOR

你可能感兴趣的:(redis,分布式,分布式,Redis)