redis基础命令

redis入门

数据结构

字符串类型

set key value
get key
incr key 当字符串是数字时递增,不是整数则报错
incrby key increment 增加指定的整数,不是整数则报错
decr key 递减,不是整数则报错
decrby key increment 减少指定的整数,不是整数则报错
incrbyfloat key increment 增加指定的双精度浮点数
append key value 值末尾追加value,键不存在则将键的值设为value,返回追加后的字符串长度
strlen key 返回值的长度
mget key [key...]获取多个值
mset key value[key value ...]设置多个键值
另外还有其他对位操作的命令

散列类型(hash)

image-20200807102214699

hset key field value 字段不存在时返回1(插入),存在返回0(更新)
hget key field 
hmset key field value [field value...]
hmget key field [field...]
hgetall key
hexists key field 判断字段是否存在,存在返回1,不存在返回0
hsetnx key field value 不存在则赋值
hincrby key field increment 增加指定的值,散列类型没有hincr命令
hdel key field [field...] 删除指定的字段,返回删除的个数
hkeys key 获取字段名
hvals key 获取字段值
hlen key 获取字段数量

列表类型(list)

列表类型(list)可以存储一个有序的字符串列表,常用的操作是向列表两端添加元素, 或者获得列表的某一个片段。列表类型内部采用双向链表(double linked list)实现。

lpush key value1[value2...] 向列表左边增加元素,返回增加元素后列表的长度。先添加		value1,顺序添加
rpush key value[value...]
lpop key
rpop key
hlen key 键不存在返回0,时间复杂度为O(1)
lrange key start stop 返回索引从start到stop的元素,包含两端,起始为0.不删除元素。
    例:LRANGE key -2 -1 支持负索引,"−1"表示最右边第一个元素,"-2"表示最右边第二个
    元素,依次类推
    例:LRANGE key 0 -1  返回全部元素,
lren key count value 会删除列表中前count个值为value的元素,返回值是实际删除的元素个数。
    (1)当 count > 0时 LREM 命令会从列表左边开始删除前 count 个值为 value的元素。
    (2)当 count < 0时 LREM 命令会从列表右边开始删除前|count|个值为 value 的元素。
    (3)当 count = 0是 LREM命令会删除所有值为 value的元素。
lindex key index 获得指定索引的元素值
lset key index 设置指定索引的元素值
ltrim key start end 删除指定索引范围之外的所有元素
linsert key before/after pivot value 会在列表中从左到右查找值为 pivot 的元素,然
	后根据第二个参数是BEFORE还是AFTER来决定将value插入到该元素的前面还是后面
rpoplpush source destination 将元素从一个列表转到另一个列表,:先执行RPOP命令再执行
	LPUSH命令。RPOPLPUSH命令会先从source列表类型键的右边弹出一个元素,然后将其加入到
	destination列表类型键的左边,并返回这个元素的值,整个过程是原子的。

集合类型(set)

在集合中的每个元素都是不同的,且没有顺序。一个集合类型(set)键可以存储至多232−1个字符串。

image-20200807112342858

sadd key member [member...] 返回加入的元素个数,已存在的元素不添加
srem key member [member...] 删除,返回删除的个数
smembers key 返回集合中所有的元素
sismember key member 判断元素是否在集合中,存在返回1,不存在返回0,个时间复杂度为O(1)
sdiff key1 [key...] 差集,返回所有属于key1,不属于其他key的元素
sinter key [key] 交集,返回每个key都包含的元素,不重复
sunion key [key] 并集,返回所有key的元素,不重复
scard key 获取集合中元素个数
sdiffstore destination key1 [key...] SDIFFSTORE命令和SDIFF命令功能一样,唯一的
	区别就是前者不会直接返回运算结果,而是将结果存储在destination键中。
sinterstore destination key [key] 
sunionstore destination key [key]
srandmember key [count] 随机获取一个或多个元素
    (1)当count为正数时,SRANDMEMBER会随机从集合里获得count个不重复的元素。如果		count的值大于集合中的元素个数,则SRANDMEMBER会返回集合中的全部元素。
    (2)当count为负数时,SRANDMEMBER会随机从集合里获得|count|个的元素,这些元素有可
    能相同
spop key 从集合中随机弹出一个元素

有序集合类型(sorted set)

在集合类型的基础上有序集合类型为集合中的每个元素都关联了一个分数,这使得我们 不仅可以完成插入、删除和判断元素是否存在等集合类型支持的操作,还能够获得分数最高 (或最低)的前N个元素、获得指定分数范围内的元素等与分数有关的操作。虽然集合中每 个元素都是不同的,但是它们的分数却可以相同。

zadd key score member [score member]如果该元素已经存在则会用新的分数替换原有的分数
zrange key start stop [withscore] 按照元素分数从小到大的顺序返回索引从 start到
	stop之间的所有元素(包含两端的元素),ZRANGE命令与LRANGE命令十分相似,如索引都是从
    0开始,负数代表从后向前查找(−1表示最后一个元素)。如果需要同时获得元素的分数的话可
    以在 ZRANGE命令的尾部加上 WITHSCORES 参数,的时间复杂度为O(log n+m)
zrangebyscore key min max[withscores] [limit offset count]该命令按照元素分数
	从小到大的顺序返回分数在min和max之间(包含min和max)的元素,如果希望分数范围不包含
    端点值,可以在分数前加上“(”符号。min和max还支持无穷大,同ZADD命令一样,-inf和
    +inf分别表示负无穷和正无穷。在本命令中 LIMIT offset count与 SQL 中的用法基本相
    同,即在获得的元素列表的基础上向后偏移offset个元素,并且只获取前count个元素。
zincrby key increment member 增加某个元素的分数,返回更改后的分数
zcard key 获得集合中元素的数量
zcount key min max 获得指定分数范围内的元素个数
zrem key member [member] 删除一个或多个元素,返回成功删除的元素数量
zremrangebyrank key start stop 按照元素分数从小到大的顺序,删除指定排名范围内的元
	素,返回删除的元素数量
zremrangebyscore key min max 删除指定分数范围内的元素,并返回删除的元素数量
zrank key member 按照元素分数从小到大的顺序获得指定的元素member的排名
zrevrank key member 按照元素分数从大到小的顺序获得指定的元素member的排名

事务

在redis中,同一个事务中运行的结果在exec命令提交后获得,所以同一个事务中无法利用上一次命令的结果。

multi  开启事务
exec  提交事务

redis不支持事务的回滚功能,语法错误(指命令不存在或者命令参数的个数不对)时,在执行exec后不会执行里面的任何语句;运行错误(指在命令执行时出现的错误,比如使用散列类型的命令操作 集合类型的键)时,其他命令依然会执行,所以需要自己手动回滚数据。

watch key 监控一个或多个键,一旦其中有一个键被修改(或删除),之后的事务就不会执行。可以解决无法获得上次命令的结果的问题,监控一直持续到EXEC 命令(事务中的命令是在 EXEC 之后才执行的,所以在 MULTI 命令后可以修改WATCH监控的键值),如果使用 WATCH命令监测了一个拥有过期时间的键,该键时间到期自动删除并不会被WATCH命令认为该键被改变。

过期时间

expire key seconds   设置key的过期时间,单位为秒,返回1设置成功,0设置失败
ttl key 返回键的剩余时间,不存在时返回-2,没有设置过期时间则返回-1
persist key 取消键的过期时间,成功返回1,否则返回0(因为键不存在或键本来就是永久的)

使用set,getset命令为键赋值会取消键的过期时间,其他操作则不会影响,pexpire和pttl则是毫秒级的操作;

持久化

RDB方式:RDB方式的持久化是通过快照(snapshotting)完成的,当符合一定条件时Redis会自动将 内存中的所有数据生成一份副本并存储在硬盘上,这个过程即为“快照”。此方式有可能丢失最后一次快照后修改的数据。Redis会在以下几种 情况下对数据进行快照:

  • 根据配置规则进行自动快照;

    在配置文件中定义,定义用例:save 900 1 ,即900秒内有一个键改动则进行快照,可以定义多个条件,只要满足其中一个就进行快照。自动快照采取异步方式。

  • 用户执行 SAVE或 BGSAVE命令;

    手动执行save命令,该命令是同步操作,回阻塞所有客户端请求;执行bgsave命令,该命令是异步操作,推荐使用,在执行时还可以通过lastsave查看最近一次成功执行快照的时间。

  • 执行 FLUSHALL命令;

    执行flushall命令会清除数据库中的所有数据,清除过程时只要自动快照条件不为空,就会执行快照,

  • 执行复制(replication)时。

    设置了主从复制时,redis会在复制初始化时进行自动快照,此过程不需要定义自动快照条件。

原理:Redis默认会将快 照文件存储在Redis当前进程的工作目录中的dump.rdb文件中,可以通过配置dir和dbfilename 两个参数分别指定快照文件的存储路径和文件名。快照的过程如下:

  1. Redis使用fork函数复制一份当前进程(父进程)的副本(子进程);

  2. 父进程继续接收并处理客户端发来的命令,而子进程开始将内存中的数据写入硬 盘中的临时文件;

  3. 当子进程写入完所有数据后会用该临时文件替换旧的 RDB 文件,至此一次快照操 作完成。

    在执行 fork的时候操作系统(类 Unix 操作系统)会使用写时复制(copy-onwrite)策略,即fork函数发生的一刻父子进程共享同一内存数据,当父进程要更改其中某片 数据时(如执行一个写命令),操作系统会将该片数据复制一份以保证子进程的数据不受影 响,所以新的RDB文件存储的是执行fork一刻的内存数据。

AOF方式:将每一条修改数据的命令追加到磁盘文件中,AOF文件位置与RDB 文件相同。AOF文件有可能存储无用的命令,可以在配置文件中设置重写AOF文件的条件:auto-aof-rewrite-percentage 100 当前文件超过上一次重写的AOF文件百分之多少会再次及逆行重写,如果之前没有重写过则以启动时的AOF文件为依据;auto-aof-rewrite-min-size 64mb 限制允许重写的最小AOF文件大小。

由于操作系统缓存的机制,每次的命令并没有即时写到磁盘AOF文件中,而是进入高速缓冲区,如果系统异常退出会丢失此部分数据,所以需要在配置文件中设置同步时机:appendfsync everysec 每秒执行一次同步操作;appendfsync always 每次执行写入都会进行同步,这是最安全最慢的方式,通常设置为everysec 。

集群

为避免单点故障,可将数据库复制成多个副本,主数据库(master)负责读写操作,从数据库(slave)只负责读操作。配置主从关系只需要在从数据库的配置文件中加入“slaveof 主数 据库地址 主数据库端口”即可,主数据库不需要进行操作。

INFO replication
SLAVEOF NO ONE
slaveof 127.0.0.1 6379
min-slaves-to-write 3 只有当3个或3个以上的从数据库连接到主数据库时,主数据库才是可写的,否则会返回错误
min-slaves-max-lag 10 允许从数据库最长失去连接的时间,这两个配置可以降低主从架构中因为网络分区导致的数据不一致的问题

原理:当从数据库启动后,会向主数据库发送sync命令,主数据库接受到后保存快照(RDB持久化),并将保存快照期间的命令缓存起来,快照完成后,主数据会将快照和缓存命令发送给从数据库,从数据库接受到后载入,此过程为复制初始化。初始化后主数据库的修改命令都会发送给送数据库。主从数据库复制数据的过程是异步的,数据会有一定时间的不同,但最终会同步。

从数据库持久化:禁用主数据库持久化,从数据库开启持久化,当从数据库崩溃后,主数据库会将数据同步过来;主数据库崩溃后,在从数据库中使用 SLAVEOF NO ONE命令将从数据库提升成主数据库继续服务,启动之前崩溃的主数据库,然后使用SLAVEOF命令将其设置成新的主数据库的从 数据库,即可将数据同步回来。此为手动维护,相对麻烦。

增量复制:解决在主从数据库连接断开后重连的问题,实现方式:

  1. 从数据库会存储主数据库的运行ID(run id)。每个Redis 运行实例均会拥有一个唯一的运行ID,每当实例重启后,就会自动生成一个新的运行ID。
  2. 在复制同步阶段,主数据库每将一个命令传送给从数据库时,都会同时把该命令 存放到一个积压队列(backlog)中,并记录下当前积压队列中存放的命令的偏移量范围。
  3. 同时,从数据库接收到主数据库传来的命令时,会记录下该命令的偏移量。

网络断开后从数据库发送psync命令,格式为“PSYNC主数据库的运行 ID 断开前最新的命令偏移量”。主数据库收到 PSYNC命令后,会执行以下判断 来决定此次重连是否可以执行增量复制。

  1. 首先主数据库会判断从数据库传送来的运行ID是否和自己的运行ID相同。(主数据库在断线期间重启过,会造成数据的不一致)
  2. 后判断从数据库最后同步成功的命令偏移量是否在积压队列中,如果在则可以 执行增量复制,并将积压队列中相应的命令发送给从数据库。

哨兵:监控redis系统的运行状况,主要功能:监控主数据库和从数据库是否正常运行;主数据库出现故障时自动将从数据库转换为主数据库。

image-20200817103433011

配置哨兵:
sentinel monitor master-name ip redis-port quorum  (可配置多个)
1.其中 master-name 是一个由大小写字母、数字和“.-_”组成的主数据库的名字,因为考虑
到故障恢复后当前监控的系统的主数据库的地址和端口会产生变化,所以哨兵提供了命令可
以通过主数据库的名字获取当前系统的主数据库的地址和端口号。
2.ip表示当前系统中主数据库的地址,而redis-port则表示端口号。
3.quorum用来表示执行故障恢复操作前至少需要几个哨兵节点同意
一个哨兵可以监控多个主从系统,一个主从系统也可以被多个哨兵监控,形成网状结构。
哨兵会与数据库建立两条连接,一条来订阅该主数据的__sentinel__:hello频道以获取其他同样
监控该数据库的哨兵节点的信息,一条发送命令

和主数据库的连接建立完成后,哨兵会定时执行下面3个操作(原理):

  1. 每10秒哨兵会向主数据库和从数据库发送INFO命令。

    获取数据库信息,哨兵通过此命令发现从数据库,并对从数据库建立两个连接

  2. 每 2 秒哨兵会向主数据库和从数据库的__sentinel__:hello 频道发送自己的信息。

    与同样监控此数据库的哨兵分享信息

  3. 每1秒哨兵会向主数据库、从数据库和其他哨兵节点发送PING命令。

    定时监控这些数据库和节 点有没有停止服务,通过down-after-milliseconds配置。

当ping的数据库或节点没有回复,则哨兵认为其主观下线,主观下线表示从当前的哨兵进程看来,该节点已经下线。如果是主数据库,则哨兵会判断是否需要进行故障恢复,哨兵发送 SENTINEL is-master-down-by-addr命令询问其他哨兵节点以了解他们是否也认为该主数据库主观下线,如果达到指定数量时,哨兵会认为其客观下线(objectively down),并选举领头的哨兵节点对主从系统发起故障恢复。数量通过quorum参数设置,当至少quorum节点认为该主数据库主观下线,则认为主数据库客观下线,进入选举领头哨兵步骤:

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

选出的领头哨兵将对主数据库进行故障恢复,首先领头哨兵将从停止服务的主数据库的从数据库中挑选一个来充当新的主数据库。挑 选的依据如下:

  1. 所有在线的从数据库中,选择优先级最高的从数据库。优先级可以通过slavepriority选项来设置。
  2. 如果有多个最高优先级的从数据库,则复制的命令偏移量越大(即复制越完整)越优先。
  3. 如果以上条件都一样,则选择运行ID较小的从数据库。

选出一个从数据库后,领头哨兵将向从数据库发送 SLAVEOF NO ONE命令使其升格为 主数据库。而后领头哨兵向其他从数据库发送SLAVEOF命令来使其成为新主数据库的从数据 库。最后一步则是更新内部的记录,将已经停止服务的旧的主数据库更新为新的主数据库的 从数据库,使得当其恢复服务时自动以从数据库的身份继续服务。

集群:使用集群将每个数据库节点的cluster-enabled配置选项打开,每个集群中至少需要3个主数据库,集群会将当前节点记录的集群状态持久化地存储在当前工作目录下的nodes.conf文件中。集群的配置可以通过辅助工具redis-trib.rb来完成。

CLUSTER MEET ip port  增加节点,增加的节点要么使用 CLUSTER REPLICATE命令复制每个主数据
库来以从数据库的形式运行,要么向集群申请分配插槽(slot)来以主数据库的形式运行。

在一个集群中,所有的键会被分配给16384个插槽,而每个主数据库会负责处理其中的一部分插槽。Redis 将每个键的键名的有效部分使用CRC16算法计算出散列值,然后取对16384的余数。有效部分指:

  1. 如果键名包含{符号,且在{符号后面存在}符号,并且{和}之间有至少一个字符, 则有效部分是指{和}之间的内容;
  2. 如果不满足上一条规则,那么整个键名为有效部分。

利用键的分配规则,可以将所有相关的键的有效部分设置 成同样的值使得相关键都能分配到同一个节点以支持多键操作。

CLUSTER ADDSLOTS slot1 [slot2] ... [slotN]  插槽没被分配过可使用此命令分配,已分配则报错
CLUSTER SLOTS  查看插槽的分配情况
CLUSTER SETSLOT 插槽号 NODE 新节点的运行 ID  插槽迁移到另一个节点,仅迁移插槽,不能迁移键值
CLUSTER GETKEYSINSLOT 插槽号要返回的键的数量   获取插槽的所有键
MIGRATE 目标节点地址 目标节点端口 键名 数据库号码 超时时间 [COPY] [REPLACE]  将键迁移到目标节点,copy表示不将键从当前数据库中删除,REPLACE表示如果目标节点存在同名键,则覆盖。因为集群模式只能使用0号数据库,所以数据库号码始终
为0。

(1)在B执行 CLUSTER SETSLOT 0 IMPORTING A。  redis-trib.rb多执行的步骤
(2)在A执行 CLUSTER SETSLOT 0 MIGRATING B。  redis-trib.rb多执行的步骤,然后再迁移

手动迁移过程中可能会造成数据临时丢失的情况,迁移时客户端访问键,但并不清楚键是在旧还是新的节点中,在redis-trib.rb中多了两个步骤来解决此问题:客户端访问旧节点时,如果不存在则返回ack跳转请求,客户端接收到请求后向新节点发送asking命令再重新发送之前的命令;客户端访问新节点时,如果前面执行过asking命令则返回结果,否则返回moved跳转请求。

客户端可以向集群中的任意一个节点发送命令,如果该键在此节点中,则正常返回,否则返回MOVE 重定向请求。客户端当发现新的重定向请求时,应该在重新向正确节点发送命令 的同时,缓存插槽的路由信息,即记录下当前插槽是由哪个节点负责的。这样每次发起命令 时,客户端首先计算相关键是属于哪个插槽的,然后根据缓存的路由判断插槽由哪个节点负 责。考虑到插槽总数相对较少(16384个),缓存所有插槽的路由信息后,每次命令将均只 发向正确的节点,从而达到和单机实例同样的性能。

集群中每个节点都会定期向其他节点发送 PING 命令,并通过有没有收到回复来判断目标节点是否已经下线了。集群中的每个节点每隔1秒钟就会随机选择5个 节点,然后向最久没有响应的节点发送PING命令,如果没有回复,则认为该目标疑似下线。一旦节点A认为节点B是疑似下线状态,就会在集群中传播该消息,所有其他节点 收到消息后都会记录下这一信息;当集群中的某一节点C收集到半数以上的节点认为B是疑似下线的状态时,就会将B标记为下线(FAIL),并且向集群中的其他节点传播该消息,从而使得B在整个集群中下线。

在集群中,当一个主数据库下线时,就会出现一部分插槽无法写入的问题。这时如果该主数据库拥有至少一个从数据库,集群就进行故障恢复操作来将其中一个从数据库转变成主数据库来保证集群的完整。选择哪个从数据库来作为主数据库的过程与在哨兵中选择领头哨兵的过程一样,都是基于Raft算法,过程如下:

  1. 发现其复制的主数据库下线的从数据库(下面称作A)向每个集群中的节点发送请求,要求对方选自己成为主数据库。
  2. 如果收到请求的节点没有选过其他人,则会同意将A设置成主数据库。
  3. 如果A发现有超过集群中节点总数一半的节点同意选自己成为主数据库,则A则成功成为主数据库。
  4. 当有多个从数据库节点同时参选主数据库,则会出现没有任何节点当选的可能。此时每个参选节点将等待一个随机时间重新发起参选请求,进行下一轮选举,直到选举成功。
posted @ 2020-09-22 14:50  带着键盘流浪  阅读(164)  评论(0)    收藏  举报