Skip to content

Head First Redis

This document is a very simple introduction to Redis, which is mainly used for personal learning and reference.

命令与配置

常用命令查询

redis命令参考

主从设置

slaveof 10.4.44.71 3904
slaveof no one
# 设置从可写 /不可写
config set slave-read-only yes
config set slave-read-only no 

内存回收策略

config get maxmemory-policy

maxmemory限制到达的时候,redis将采取的准确行为是由maxmemory-policy配置指令配置的。以下策略可用:

  • noeviction:当到达内存限制时返回错误。当客户端尝试执行命令时会导致更多内存占用(大多数写命令,除了DEL和一些例外)。如果对数据非常敏感,不允许丢失数据,那么建议使用noeviction策略。
  • allkeys-lru:回收最近最少使用(LRU)的键,为新数据腾出空间。如果分为热数据与冷数据, 推荐使用allkeys-lru策略
  • volatile-lru:回收最近最少使用(LRU)的键,但是只回收有设置过期的键,为新数据腾出空间。
  • allkeys-random:回收随机的键,为新数据腾出空间。如果需要循环读写所有的key, 或者各个key的访问频率差不多, 可以使用allkeys-random策略, 即读写所有元素的概率差不多
  • volatile-random:回收随机的键,但是只回收有设置过期的键,为新数据腾出空间。
  • volatile-ttl:回收有设置过期的键,尝试先回收离TTL最短时间的键,为新数据腾出空间。

复制 Replication

调整复制超时时间

config get repl-timeout
config set repl-timeout 1800

调整复制缓冲区大小

slave后的两个参数分别表示硬限制和软限制: 硬限制到达就无法写入. 软限制标识连续60s达到这个数值

config set client-output-buffer-limit "slave 2684354560 536870912 0"

设置复制积压缓冲区的大小

config get repl-backlog-size
config set repl-backlog-size xx
(unit: bytes)

持久化

设置重写的大小 80GB

config set auto-aof-rewrite-percentage 200
config set auto-aof-rewrite-min-size 80108864000

通过 aof 回放命令

tail -n +6 /opt/redis_dump/appendonly.aof | pv -L 10m | nc 10.13.56.15 3707 > ~/run.log

关闭 AOF

config set appendonly no

AOF 写满

aof写满磁盘的问题 磁盘满了aof写失败,而磁盘上没有别的空间可以释放 通过一下方式清空后再清空aof文件再bgrewrite

>appendonly.aof

如果直接删除aof文件,磁盘空间不会释放,因为文件句柄没有全部释放。这时候可以用以下命令来清空已经删除的文件

>/proc/${pid}/fd

集群

查看 cluster nodes 拓扑分布

redis-cli -h 10.3.23.27 -p 3920 cluster nodes

将一个新节点加入到现有集群中

选择原有集群中的任意一个节点10.3.23.35:3920,加入新的节点10.3.20.213:3920

redis-cli -h 10.3.23.35 -p 3920 CLUSTER MEET 10.3.20.213 3920

设置从节点

设置10.3.20.213 3920node-id(fd276dc8e818f53239f988dc2bb3ec85504f9096)的从节点:

redis-cli -h 10.3.20.213 -p 3920
 CLUSTER REPLICATE fd276dc8e818f53239f988dc2bb3ec85504f9096

从集群中重置一个节点

首先从集群拓扑中删除该节点,然后清空重置该节点数据,最后再加入到集群中 eg: 要操作的节点为10.3.20.213:3920,其node-idfd276dc8e818f53239f988dc2bb3ec85504f9096

# 对集群中所有节点发送forget 该节点的命令
redis-cli -h 10.3.1.1 -p 3920 
 CLUSTER FORGET fd276dc8e818f53239f988dc2bb3ec85504f9096
# 连接该节点,清空数据并重置
redis-cli -h 10.3.20.213 -p 3920
  FLUSHALL
  CLUSTER RESET
# 连接任意一个节点,将新节点加入:
redis-cli -h 10.3.1.1 -p 3920 CLUSTER MEET 10.3.20.213 3920

查看集群中指定 slot 中的key的数量

redis-cli -h 10.3.23.35 -p 3920 CLUSTER COUNTKEYSINSLOT 11587

设置 slot 在特定节点上

redis-cli -h 10.3.21.50 -p 3920 CLUSTER SETSLOT 11587 NODE f68aa3484f2340a9586632b2696f5a8fe0b30f40

设置集群的超时时间

系统默认为5s

config set cluster-node-timeout 30000

cluster rebalance

redis-cli --cluster rebalance ip:port

  rebalance      host:port
                 --cluster-weight <node1=w1...nodeN=wN>
                 --cluster-use-empty-masters
                 --cluster-timeout <arg>
                 --cluster-simulate
                 --cluster-pipeline <arg>
                 --cluster-threshold <arg>
                 --cluster-replace

cluster failover

主从都为存活状态,将slave切换为master

slave-node-cli> CLUSTER FAILOVER

master挂掉,将slave切换为master

slave-node-cli> CLUSTER FAILOVER [FORCE|TAKEOVER]
  • FORCE选项: 不与master握手,广播信息,与其集群其它master通信,获取授权投票成为新的master
  • TAKEOVER选项:不与master握手,也不需获取其他master投票通过,直接提升为master (应用场景:数据中心切换时将大量的slave设置为master,但此时 大多数master都不可用,或者发生了脑裂)

注:TAKEOVER violates the last-failover-wins principle of Redis Cluster ref: https://redis.io/commands/cluster-failover

slot 迁移过程

1.设置目标节点为 importing state

CLUSTER SETSLOT <slot> IMPORTING <source-node-id>.
  • 直接请求这个slotkey,返回MOVED转向
  • 先发送ASKING命令,再请求这个slotkey,处理请求

2.设置源节点为 migrating state

CLUSTER SETSLOT <slot> MIGRATING <destination-node-id>.
  • 请求已存在的key,和原有处理逻辑一致
  • 请求不存在的key,给client返回ask转向,client请求importing的节点
  • 请求包含多个key,部分存在部分不存在的时,返回TRYAGAIN,直到所有的key都被迁移

3.从源节点循环读取出key, 然后将他们转移到目标节点

CLUSTER GETKEYSINSLOT
MIGRATE host port key "" destination-db timeout REPLACE KEYS key [key ...]]

4.设置slots状态为正常:

 CLUSTER SETSLOT <slot> NODE <destination-node-id>
 # in the source and destination 

CLUSTER SETSLOT <slot> NODE <node-id>,一般用于迁移slot完成之后,对迁移状态的两个实例发送该命令

作用:

  • slot属主执行这条命令,返回错误
  • slot处于migrating的实例执行这条命令,清除migrating状态
  • slot处于importing的实例执行这条命令,清除importing状态,并检查epoch id,如果epoch id不是集群中最大的,生成一个新的最大id(注意:此时并不和集群通信,手动重置为最大)

注:如果迁移过程中断,修改状态,对待修复的节点执行

redis-cli  -h <host> -p <port> cluster setslot <slot> stable

注:just clear migrating / importing state https://redis.io/commands/cluster-setslot

client 工具

查看当前的连接到服务器的客户端的列表

127.0.0.1:6379> client list
addr=127.0.0.1:52555 fd=5 name= age=855 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=32768 obl=0 oll=0 omem=0 events=r cmd=client
addr=127.0.0.1:52787 fd=6 name= age=6 idle=5 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=ping

每一行表示一个连接的各项信息:

  • addr: 客户端的TCP地址,包括IP和端口
  • fd: 客户端连接socket对应的文件描述符句柄号
  • name: 连接的名字,默认为空,可以通过CLIENT SETNAME设置
  • age: 客户端存活的秒数
  • idle: 客户端空闲的秒数
  • flags: 客户端的类型 (N表示普通客户端,更多类型见 https://redis.io/commands/client-list)
  • omem: 输出缓冲区的大小
  • cmd: 最后执行的命令名称

查看当前正在执行的命令

monitor

Big Keys

大key不仅会降低proxy的吞吐率,并且容易诱发阻塞,平响长尾也会变大,最好压缩后再存放。

查看

slowlog get {N}
memory usage KEY
debug object key
// serializedlength不代表真实的字节大小,它返回对象使用RDB编码序列化后的长度,值会偏小,但是对于排查bigkey有一定辅助作用
redis-cli --stat
redis-cli -h {ip} -p {port} bigkeys
redis-cli -h {ip} -p {port} --latency

不建议

  • string类型的大小不超过10KB
  • HASH, SET, ZSET, LIST元素不宜超过1000.
  • 不建议使用hgetalllrange, mget, mset一次性获取上千个元素
  • 在元素过大、个数过多时,不建议全量查询元素,比如zrange key 0 -1命令会导致慢查询
  • 不建议pipeline批次下key数量超过500,最好控制在100以内

建议

  • string类型建议1k之内,对于大于10k的json串建议采用压缩方式存储
  • 建议打散过期时间,防止数据集中过期阻塞
  • redis对于元素个数少和value小的数据有压缩算法,可以降低redis本身的数据结构开销
类型个数最大值
Hash512
Set512
Zset128
List512

数据类型与实现

/images/redis-data-type.webp

Best Practice

/images/redis-best-practice.webp

/images/redis-dev.png

/images/redis-ops.webp

Reference

  • https://mp.weixin.qq.com/s/Fz1EbsmJP5k2Rh6ir_a1pQ

Disclaimer
  1. License under CC BY-NC 4.0
  2. Copyright issue feedback me#imzye.me, replace # with @
  3. Not all the commands and scripts are tested in production environment, use at your own risk
  4. No privacy information is collected here
Try iOS App