redis的学习入门笔记

趁着周末时间,自己整理了一下redis的学习笔记,整个文章篇幅比较长,包涵了redis中最常用的数据类型以及常用操作命令;相关常用的配置文件以及持久化、事务、复制、调试等相关知识。

一、数据库相关操作:


选择某个编号数据库:

select  num[0-15]

清空当前库:

flushdb

清空所有库:

flushall

查看当前库大小,key数量

dbsize  

二、key 相关操作:


exists key  
#检测key是否存在

move key db
#将key移动到其他数据库

expire/pexpire key time
#设置key的过期时间,单位秒;带p的单位是毫秒

expireat/pexpireat key timestamp
#设置key在某个linux时间戳过期;带p的单位是毫秒

PERSIST key
#移除key的生存时间,变为持久的,不过期的key

ttl/pttl key
#查看key还有多少秒过期,-1永不过期,-2已过期;带p的单位是毫秒

type key
#查看key的类型

del key
#删除key

rename key newkey
#重命名key为newkey
当 key 和 newkey 相同,或者 key 不存在时,返回一个错误。
当 newkey 已经存在时,其值将被覆盖

renamenx key newkey
#当且仅当 newkey 不存在时,将 key 改名为 newkey

scan:增量式迭代获取数据库中的key,每次返回游标部分元素

与之类似命令:

SSCAN 命令用于迭代集合键中的元素。
HSCAN 命令用于迭代哈希键中的键值对。
ZSCAN 命令用于迭代有序集合中的元素(包括元素成员和元素分值)。

特点:可以用于生产环境。不同于keys * 或者 smembers(会阻塞服务器)

用法:

SCAN cursor [MATCH pattern] [COUNT count]

参数说明:
   cursor:游标,被设置为 0 时,表示第一次执行

   match:匹配规则,比如匹配hello,可以写 hel*

   count :在每次迭代中应该从数据集里返回元素数量,默认值为 10

cursor说明:我们一直调用 SCAN 命令, 直到命令返回游标 0 , 此时为一次完整遍历(full iteration)

示例:

redis 127.0.0.1:6379> scan 0 count 10
1) "0"
2)  1) "name"
    2) "age"
    3) "k1"
    4) "k2"
    5) "k3"

三、string常用操作(单值单value):


set key value
#设置key的值为value

get key
#获取key的值

append key value
#将value附加到key的后面

strlen key
#获取key的长度

incr/decr key
#对key每次 +1/-1操作,key的值必须数字

incrby/decrby key n
#对key每次 +n/-n操作

getrange key 0 [-1]
#获取key指定长度范围的值,-1表示获取完整值

SETRANGE key offset value
#设置key的值,从offset的位置,被替换为value

setex key expire value
#设置带过期时间的key,比如 setex name 10 houger

setnx key value
#当key不存在,则设置成功

mset/msetnx key1 v1 key2 v2
#同时设置多个key,val
#msetnx时,只有key都不存在时,才能设置成功

mget key1 key2
#同时获取多个值

四、list类型(单值多value):


lpush/rpush key value ...
#将多个value从 左侧/右侧 插入到list中

lrange key start end [-1]
#获取从start到end的values ,-1表示获取全部

lpop/rpop key
#从 左侧/右侧 弹出一个value

lindex key n[下标]
#获取下标为 n 的value

llen key
#获取key的长度

lrem key count value
#删除 count 个值为value的值

ltrim key start stop
#获取从下标start 到stop范围的值,并赋值给key,key的值被重写

rpoplpush key1 key2
#从key1右侧弹出一个value,插入到key2 左侧,并返回该value

lset key index value
#重新设置下标为index 的值为value

linsert key before/after v1 v2
#在 v1 之前/之后 插入v2

注意:list是一个字符串链表。left,right都可以插入value;如果键不存在,则创建新的链表;如果键已存在,则新增内容;如果值全部移除,则对应key也就消失了。

五、set集合(单值多values):


sadd key v1 v2 v3
#往集合中添加values

smembers key
#获取集合中所有元素

sismember key value
#判断key中是否存在value,存在返回1,不存在返回0

scard key
#获取key中元素个数

srem key v1 v2 ..
#删除集合中多个元素

srandmember key count
#从key中随机获取 count 个value

spop key
#随机出栈

smove key1 key2 v1
#将key1 中的v1 移动到 key2中

数据集合运算:

获取两个集合的差集:

sdiff key1 key2
#获取只存在key1中的values,不存在于key2中

获取两个集合的交集:

sinter key1 key2
#获取同时存在于key1于key2中的值

获取两个集合中并集:

sunion key1 key2

六、hash类型操作(kv模式,v是一个键值对):


hset key field value
#设置一个key,key中有一个k,v键值对
hset user id 10
hset user name houger

hget key field
#获取key中field的value

hmset/hmget
#同时获取/设置 多个field

hgetall key
#获取key中所有键值对

hdel key field [...]
#删除一个或多个键值对

hlen key
#获取key的长度

hexists key field
#检测key中是否存在某个field

hkeys/hvals key
#获取key中所有 fields/values

hsetnx key field value
#只有在字段 field 不存在时,设置哈希表字段的值

hincrby/hincrbyfloat key field increment
#为 key 中的指定字段field 的整数/浮点数 值加上增量 increment

七、zset有序集合(单值多value,每个value有一个score权重)


zadd key score value
#往集合中添加一个value,权重为score

zrange key 0 -1 [withscores]
#获取集合中value

zrevrange key 0 -1 [withscores]
#按照score 递减排序获取集合中value

zrangebyscore/zrevrangebyscore key start  (stop limit [start len]
#获取权重 在 start - stop中的values,左括号的意思是不包含该值


zrem key value
#删除key中值为value的元素

zcard key
#获取key中的元素个数

zcount key start stop
#获取score 在 start - stop中元素个数

zrank key value
#返回有序集合中指定成员的索引

zrevrank key value
#按照倒叙 返回有序集合中指定成员的索引

zscore key value
#返回有序集中,成员的分数值

zunionstore newkey  num key1 key2
#获取给定的一个或多个有序集的并集,存储到新的集合newkey中

八、redis.conf配置分析:


daemonize yes
#配置是否守护进程启动

pidfile /var/run/redis.pid
#守护进程启动时,生成的进程ID文件

port 6379
#默认端口号

timeout 0
#客户端在空闲多长时间后关闭连接,默认0 ,不关闭

tcp-keepalive 300
#保持tcp连接的活跃时间

loglevel notice
#日志级别
 debug :开发测试阶段使用
 verbose:包含很多不太有用的信息,但比debug要清爽一些
 notice:适用于生产环境
 waring:记录警告信息

logfile ""
#日志记录位置

syslog-enabled no
#系统日志开关,默认关闭

requirepass [password]
#为redis添加密码,客户端链接需要 auth 认证

rdbcompression
#指定存储至本地数据库时是否压缩数据,默认为yes,redis采用lzf压缩,如果为了节约cpu时间,可以关闭该选项,这样会导致数据库文件过大。

dbfilename dump.rdb
#指定本地数据库文件名,默认值为dump.rdb

dir ./
#本地数据库存放目录

slaveof <master ip> <master port>
#当本机设置为slave时,设置master服务的ip及端口,在redis启动时,他会自动从master进行数据同步

masterauth
#当master服务启动了密码时,slav连接maser的密码

九、limits相关配置


maxclients 10000
#最大连接客户端

maxmemory
#最大使用内存,0 表示不限制

maxmemory-policy
#内存淘汰策略,默认noeviction

maxmemory-samples
#redis会设置一个采样值,在采样值范围内,使用LRU和TTL。maxmemory-samples就是采样值的定义,缺省是5,作者的建议,已是最佳。

十、查看redis服务信息


查看所有信息redis-cli info,会列出包括ClientsMemoryPersistenceStatsReplication CPUClusterKeyspace相关信息。如果查看某一项信息,直接跟上对应参数即可。

查看redis内存使用情况

redis-cli info memory
used_memory:848600
used_memory_human:828.71K
used_memory_rss:2273280
used_memory_rss_human:2.17M
used_memory_peak:848600
used_memory_peak_human:828.71K
.....

参数值说明:

used_memory: redis当前数据使用的内存,有可能包括SWAP虚拟内存。

used_memory_rss: redis当前占用的物理内存,包括内存碎片。此值和用top命令查看的进程占用内存一致。

mem_fragmentation_ratio:,当mem_fragmentation_ratio <1 时,说明used_memory > used_memory_rss,这时Redis已经在使用SWAP,运行性能会受很大影响。通常在正常情况下,该值比1大一些。

查看redis的状态

redis-cli info  stats
total_connections_received:2
total_commands_processed:1
instantaneous_ops_per_sec:0
total_net_input_bytes:51
...

参数说明:

instantaneous_ops_per_sec:每秒操作数

查看其他相关信息:

redis-cli info cpu 查看cpu信息

redis-cli info replication 主从信息、角色、服务状态等

Keyspace键的相关信息,如键数量,过期数量,平均生育时间等

十一、redis压力测试


redis-benchmark -n 100000 -c 10000 -t set
-n 总共请求数
-c 并发请求数
-a auth认证口令
-p 端口号
-h 主机ip
-d 模拟请求数据的大小,默认3 bytes
--dbnum <db>默认操作的数据库编号,默认 0
-t 操作动作,比如 set、get等操作

十二、rdb持久化


简介:在指定的时间内,将内存中的数据快照写入磁盘。它恢复时是将快照文件直接读到内存里。

运行方式:redis会单独创建(fork)子进程来进行持久化,会先将数据写入到一个临时文件,待持久化过程结束后,再用这个临时文件替换掉上次持久化好的文件。

整个过程主进程是不进行任何I/O操作,这确保了极高的性能。

如果需要进行大规模的数据恢复,且对数据恢复的完整性不是非常敏感,则rdb方式要比AOF方式更佳高效,但缺点是最后一次持久化的数据可能丢失。

触发条件:

save 900 1
save 300 10
save 60 10000

每当900秒内有1 个key,300秒内有10个key,60秒内有10000个key被设置,将会触发快照。

相关配置参数:

  • stop-writes-on-bgsave-error :默认值为yes。当启用了RDB且最后一次后台保存数据失败,Redis是否停止接收数据
  • rdbcompression:默认值是yes。对于存储到磁盘中的快照,可以设置是否进行压缩存储。如果是的话,redis会采用LZF算法进行压缩。如果你不想消耗CPU来进行压缩的话,可以设置为关闭此功能,但是存储在磁盘上的快照会比较大
  • rdbchecksum :默认值是yes。在存储快照后,我们还可以让redis使用CRC64算法来进行数据校验,但是这样做会增加大约10%的性能消耗,如果希望获取到最大的性能提升,可以关闭此功能。
  • dbfilename:设置快照的文件名,默认是 dump.rdb
  • dir:设置快照文件的存放路径

手动触发rdb:

  • save:该命令会阻塞当前Redis服务器,执行save命令期间,Redis不能处理其他命令,直到RDB过程完成为止
  • bgsave:执行该命令时,Redis会在后台异步进行快照操作,快照同时还可以响应客户端请求。具体操作是Redis进程执行fork操作创建子进程,RDB持久化过程由子进程负责,完成后自动结束
  • flushall :也会触发生成dump.rdb文件,不过是一个空文件,被清空的。
  • lastsave:返回最近一次 Redis 成功将数据保存到磁盘上的时间,以 UNIX 时间戳格式表示。

恢复数据:

首先我们查看redis安装目录:config get dir,将dump.rdb文件拷贝到此目录,待redis启动后,会自动加载数据到内存。

rdb优势:

  • rdb是一个非常紧凑的备份文件,它保存了redis在某个时间点的数据集,这种文件非常适合用于备份。
  • rdb 非常适用于灾难恢复(disaster recovery):它只有一个文件,并且内容都非常紧凑,可以(在加密后)将它传送到别的数据中心
  • rdb 在恢复大数据集时的速度比 AOF 的恢复速度要快

rdb劣势:

  • 在一定间隔内做一次备份,如果redis意外挂掉,有可能会丢失最后一次快照内容
  • 每次fork时,内存中数据被克隆了一份,增大了性能消耗

十三、AOF持久化


简介:以日志的形式记录每个写操作,将redis执行的每个写操作记录下来。只许追加文件但不可改写文件,redis启动之初会读取该文件重新构建数据。redis重启的话就根据日志文件内容将写指令从前到后执行一次以完成数据的恢复工作。

开启appendonly:

#修改配置文件:
appendonly yes

-----或者-----

#在客户端窗口执行:
CONFIG SET appendonly yes

触发策略:

appendfsync always  #每执行一次写操作,执行一次,性能差,数据完整
appendfsync everysec#每秒执行一次
appendfsync no      #从不执行

相关配置参数:

no-appendfsync-on-rewrite no
#重写时是否可以运用appendfsync,默认no,保证数据安全

auto-aof-rewrite-min-size 64mb
#设置允许重写的最小aof文件大小,避免了达到约定百分比但尺寸仍然很小的情况还要重写。

auto-aof-rewrite-percentage
#默认值为100。aof自动重写配置,当目前aof文件大小超过上一次重写的aof文件大小的百分之多少进行重写,即当aof文件增长到一定大小的时候,Redis能够调用bgrewriteaof对日志文件进行重写。当前AOF文件大小是上次日志重写得到AOF文件大小的二倍(设置为100)时,自动启动新的日志重写过程。

AOF修复:

当aof文件被破坏或者启动无法被加载时,我们可以使用redis-check-aof --fix appendonly.aof修复。

AOF重写:

由于AOF持久化是Redis不断将写命令记录到 AOF 文件中,随着Redis不断的进行,AOF 的文件会越来越大,文件越大,占用服务器内存越大以及 AOF 恢复要求时间越长。为了解决这个问题,Redis新增了重写机制,当AOF文件的大小超过所设定的阈值时,Redis就会启动AOF文件的内容压缩,只保留可以恢复数据的最小指令集。可以使用命令 bgrewriteaof 手动触发重写。

重写原理:

AOF文件持续增长而过大时,会fork一个子进程,AOF文件进行重写(先写入临时文件,文件最后在rename)。遍历新进程的内存数据,每条记录有一条set语句。重写aof文件操作,并没有读取旧的aof文件,而是将整个内存中的数据内容用命令的方式重写了一个新的aof文件。

注意:因为子进程在进行 AOF 重写期间,服务器进程依然在处理其它命令,这新的命令有可能也对数据库进行了修改操作,使得当前数据库状态和重写后的 AOF 文件状态不一致。

为了解决这个数据状态不一致的问题,Redis 服务器设置了一个 AOF 重写缓冲区,这个缓冲区是在创建子进程后开始使用,当Redis服务器执行一个写命令之后,就会将这个写命令也发送到 AOF 重写缓冲区。当子进程完成 AOF 重写之后,就会给父进程发送一个信号,父进程接收此信号后,就会调用函数将 AOF 重写缓冲区的内容都写到新的 AOF 文件中

重写触发机制:

通过 配置文件中的auto-aof-rewrite-percentage:默认值为100,以及auto-aof-rewrite-min-size64mb 配置,也就是说默认Redis会记录上次重写时的AOF大小,默认配置是当AOF文件大小是上次rewrite后大小的一倍且文件大于64M时触发。

AOF优点:

  • AOF可以保证数据集的高度完整性,假如设置每一秒中执行一次AOF操作,我们最多只会损失一秒中的数据。
  • AOF 文件是一个只进行追加操作的日志文件,并且可以使用redis-check-aof 修复AOF文件命令不完整等问题
  • AOF 文件有序地保存了对数据库执行的所有写入操作,即使我们误操作执行flushall操作,只要AOF文件未被重写,我们就可以将AOF文件末尾flushall移除即可。

AOF缺点:

  • 对于相同的数据集来说,AOF 文件的体积通常要大于 RDB 文件的体积
  • 根据所使用的 fsync 策略,AOF 的速度可能会慢于 RDB

汇总:

同时开启两种持久化机制时,当redis重启时,会优先加载AOF文件恢复数据,因为在通常情况下,AOF保存的数据要比rdb数据完整。rdb保存的数据不实时,同时使用两者时,服务器重启也只会找AOF,那要不要只使用AOF备份呢?官方建议还是开启rdb,因为rdb更适合用于数据的备份(AOF在不断变化,持续的IO,不好备份),AOF可能存在潜在的bug。

十四、事务


介绍:

可以一次执行多个命令,本质是一组命令的集合。一个事务中所有的命令都会被序列化,按顺序的串行化执行,过程中不会被其他命令插入。

使用流程:

> MULTI     #开启事务,返回OK
OK
> INCR foo  #操作key,value,
QUEUED      #添加到queued队列,等待执行
> INCR bar
QUEUED
> EXEC      #提交事务
1) (integer) 1
2) (integer) 1

DISCARD    #清空事务队列,并退出事务

事务错误处理:

  • 错误发生在添加到队列(queued)时,发生error,也就是说在调用exec之前,命令报错,此时如果提交事务,事务将终止执行,并返回错误
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set k1 v1
QUEUED
127.0.0.1:6379> set k2 v2
QUEUED
127.0.0.1:6379> sdfs
(error) ERR unknown command 'sdfs'
127.0.0.1:6379> EXEC
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379>

看上述代码,我们随便输入了一个不存在命令,返回err,再执行exec,事务被终止执行,所有命令执行失败。

  • 错误发生在exec之后,也就是我们添加到事务的命令都是返回queued,但是执行exec返回error,此时在queued中,某些命令执行失败,但是不影响其他能够执行成功的命令。
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set kk2 vv2
QUEUED
127.0.0.1:6379> INCR kk2
QUEUED
127.0.0.1:6379> set kk3 vv3
QUEUED
127.0.0.1:6379> get kk3
QUEUED
127.0.0.1:6379> exec
1) OK
2) (error) ERR value is not an integer or out of range
3) OK
4) "vv3"
127.0.0.1:6379>

我们看到,exec之后发生了错误,但是不影响其他命令正确执行。

watch监控:

悲观锁:(Pessimistic Lock)每次去拿数据的时候都会认为别人会修改,所以每次在拿数据的时候都会上锁。这样当别人再想拿这个数据时就会block(阻塞)直到它拿到锁。传统数据库里面就会用到很多这种锁机制,行锁、表锁、读写锁等,都是在操作前先上锁。

乐观锁:(Optimistic Lock)很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁。但是在更新的时候会判断一下在此期间别人有没有去更新这个数据。可以使用版本号等机制控制。乐观锁适用于多读的应用类型,可以提高吞吐量。

乐观锁策略:提交版本必须大于记录当前版本才能执行更新。

用法:

watch key[keys ...]
监视一个或者多个key,如果在执行事务之前,这个key 被改动,那么事务将被打断

unwatch
取消watch命令对所有的key的监视

总结watch指令,类似乐观锁,事务提交时, 如果key的值已经被别的客户端修改,那么整个事务队列将不会被执行;通过 watch在事务开启之前键控了多个keys,倘若在watch之后有任何key的值发生了变化,exec执行的事务都将被放弃。

事务特性汇总:

  1. 单独的隔离操作:事务中的所有命令都会序列化、按顺序执行。事务在执行的过程中不会被其他客户端发送的命令打断。
  2. 没有隔离级别的概念:队列中的命令没有提交之前,都不会被实际执行,因为事务提交之前,任何指令都不会被实际执行,所以也就不存在”在事务内部能够查询到事务内的更新,事务外部查询不到更新(关系型数据库可以)”
  3. 不保证原子性:redis中事务中如果有一个命令执行失败,其后续的命令仍然可以被执行,不会回滚。

十五、主从复制


redis是支持主从复制功能,跟mysql类似。

一主多仆:

我们配置从库即可:修改配置文件,找到此项slaveof <hostname> <port>,将master信息填写即可;或者我们在从库客户端窗口运行slaveof <hostname> <port>也是可以的。需要注意的是在命令行窗口设置后,服务被重启后,从库会断开与主库的联系,我们需要重新建立主仆关系。

注意:假如主库在运行中突然停掉,此时不影响从库的访问,但是从库的角色不会改变。待主库重启后,关系会自动建立。

反客为主:将当前的从库恢复成为主库,命令:slaveof no one

复制原理:

slave启动成功连接到master后,会发送一个sync命令,master接到命令启动后台的存盘进程,同时收集所有接收到的用于修改数据集命令,在后台进程执行完毕后,master将会传送整个数据文件到slave,以完成一次完全同步、全量复制;slave服务在接收到数据库文件数据后,将其存盘并加载到内存中。

增量复制:master继续将新的所有收集到的修改命令一次传递给slave,完成同步。但是只要是重新连接master,一次完全同步将被自动执行。

哨兵Sentinel:

顾名思义,Sentinel用于监控redis服务器的运行状态。它的作用主要有三个:

  • 监控(Monitoring)Sentinel 会不断地检查你的主服务器和从服务器是否运作正常
  • 提醒(NOTIFICATION)当被监控的某个 Redis 服务器出现问题时, Sentinel 可以通过调用bash脚本向管理员发送通知
  • 自动故障迁移(Automatic failover):当主服务器不能正常工作时,哨兵会开始故障迁移操作,会在失效的主服务器中的从服务器中选取一个作为新的主服务运行。

配置参数:

monitor <master-name> <ip> <redis-port> <quorum>:监视一个主机名为mastername 的主服务器,填写正确的ip和port

注:quorum:表示判断这个主服务器失效,需要多个 Sentinel 同意 (只要同意 Sentinel 的数量不达标,自动故障迁移就不会执行)

down-after-milliseconds指定了 Sentinel 认为服务器已经断线所需的毫秒数。

parallel-syncs 选项指定了在执行故障转移时, 最多可以有多少个从服务器同时对新的主服务器进行同步, 这个数字越小, 完成故障转移所需的时间就越长

notification-script <master-name> demo.sh:主机发生故障,执行提醒通知脚本

十六、调试


  1. ping测试服务是否正常运行

使用示例:

127.0.0.1:6379> ping
PONG

#连接正常返回pong
#连接不正常会返回连接失败错误信息
  1. SLOWLOG慢日志,用来记录查询执行时间的日志系统,与mysql的慢日志都差不多。

设置方式:

配置文件:slowlog-log-slower-than 时间阀值,设置的时间阀值单位是微秒(1秒 = 1000,000微秒)

动态设置:我们通过config getcondig set动态设置获取时间阀值。

使用示例:

CONFIG SET slowlog-log-slower-than 1000

上述命令将会记录所有查询时间大于 1000微秒的查询。

我们可以配置slowlog-max-len,它决定slow log最多能保存多少条记录。slow log本身是一个队列,当记录数超过配置值时,最旧的日志记录将被删除。我们来配置它的值:

config set slowlog-max-len 1000

查看slow log:

使用命令:slowlog get [number],number为缺省值,默认打印全部slow log,可以获取指定数量日志。

查看当前已经记录日志数量:slowlog len

清空日志记录:slowlog reset

  1. monitor:监控redis服务器实时接收到的命令,实时打印

示例:

127.0.0.1:6379> monitor
OK
1558754167.094505 [0 127.0.0.1:51589] "COMMAND"
1558754171.886346 [0 127.0.0.1:51589] "get" "name"
1558754178.015959 [0 127.0.0.1:51589] "set" "k1" "v1"

参考文献:

redis命令参考

redis官方手册

发表评论

电子邮件地址不会被公开。 必填项已用*标注