redis 第二节 redis 入门使用

Redis 简介

Redis是一个开源(BSD许可),内存数据结构存储,用作数据库,缓存和消息代理。它支持数据结构,如 字符串散列列表集合,带有范围查询的排序集位图超级日志和带有半径查询的地理空间索引。Redis具有内置复制Lua脚本LRU驱逐事务和不同级别的磁盘持久性,并通过Redis Sentinel提供高可用性和Redis Cluster自动分区。

你可以 对这些类型运行原子操作,例如附加到字符串 ; 递增哈希值 ; 将元素推送到列表中 ; 计算集合交集并集差异 ; 或者在排序集中获得排名最高的成员

为了实现其出色的性能,Redis使用 内存数据集。根据您的使用情况,您可以通过 每隔一段时间将数据集转储到磁盘或通过将每个命令附加到日志来保留它。如果您只需要功能丰富的网络内存缓存,则可以选择禁用持久性。

Redis还支持简单到设置的主从异步复制,具有非常快速的非阻塞第一次同步,自动重新连接以及在网络分割上的部分重新同步。

Redis 安装

windows 安装

  官方没有windows版本的支持,但是微软维护这一个windows 64位的redis版本,代码托管在github上,可以使用该地址进行下载,https://github.com/MicrosoftArchive/redis/releases

  按照需要进行下载文件,解压后redis对应的服务程序为redis-server.exe,配置文件为 redis.windows.conf,启动完成后,使用redis-cli.ext -h127.0.0.1 -p6379 来对redis数据库进行操作。

Linux 安装

到官网下载redis的安装包 Redis官网 下载对应的linux的操作系统的安装包(分为稳定,不稳定和测试三个版本)。

具体操作如下:

# 下载源码包
wget http://download.redis.io/releases/redis-4.0.11.tar.gz
# 解压
tar xzf redis-4.0.11.tar.gz
# 切换工作目录
cd redis-4.0.11
# make 编译
make
# 编译好的二进制文件在src目录下。
# 可以自行拷贝进行使用,也可以使用make install命令安装。
# 如果执行make install 默认文件被放到/usr/local/bin/下,也可以使用 PREFIX=/to/path 参数来指定存放位置
make install PREFIX=/usr/local/

Redis 配置

  redis的配置文件位于redis目录下,文件名为redis.conf,配置文件的修改可以通过修改配置文件重启redis来使配置文件生效,或者使用CONFIG SET|GET 命令来进行动态配置。

Redis 数据持久化

Redis是个支持持久化的内存数据库,redis需要经常将内存中的数据同步到磁盘来保证持久化。

RDB 方式

RDB 方式为默认的快照方式。

配置

# 该配置一般为默认配置
save 900 1       #在900秒(15分钟)之后,如果至少有1个key发生变化,则dump内存快照。
save 300 10      #在300秒(5分钟)之后,如果至少有10个key发生变化,则dump内存快照。
save 60 10000    #在60秒(1分钟)之后,如果至少有10000个key发生变化,则dump内存快照。

工作原理

RDB方式持久化命令如下:

命令说明
SAVE 运行后会阻塞Redis服务器进程,直到RDB文件创建完毕,在阻塞过程过程中服务器不处理任何来自外界的请求无论读还是写(阻塞所有请求)。
BGSAVE 会产生一个子进程,由此子进程来处理创建RDB文件任务,而服务器的父进程继续响应外部请求。
BGREWRITEAOF 用于异步执行一个 AOF(AppendOnly File) 文件重写操作。重写会创建一个当前 AOF 文件的体积优化版本。 即使 Bgrewriteaof 执行失败,也不会有任何数据丢失,因为旧的 AOF 文件在 Bgrewriteaof 成功之前不会被修改。 (注意: 从 Redis 2.4 开始, AOF 重写由 Redis 自行触发, BGREWRITEAOF 仅仅用于手动触发重写操作。 )
LASTSAVE 返回最近一次 Redis 成功将数据保存到磁盘上的时间,以 UNIX 时间戳格式表示。

BGSAVE在执行过程中不会阻塞请求,但是不是任何请求都可以执行,在服务器执行BGSAVE期间,对于执行SAVEBGSAVEBGREWRITEAOF这三个命令会有所有不同。

在BGSAVE执行期间 
执行SAVE命令 会被服务器拒绝,服务器禁止SAVE命令和BGSAVE同时执行,因为不可能让两个命令去调用同一函数然后去操作同一个RDB文件。
执行BGSAVE命令 会被服务器拒绝,因为已经有一个在进行了,没必要再允许一个 。
执行BGREWRITEAOF命令 会被延迟执行,BGSAVE子进程完成后,才会执行BGREWRITEAOF命令 。
在BGSAVE执行期间 
执行BGSAVE命令 会被拒绝,这两个命令没有冲突的地方,只是同时执行会产生大量磁盘写操作,会影响性能,所以这是一个规则上的拒绝,不是一个技术上的拒绝

BGSAVE 工作原理

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

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

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

查看rds文件配置

通过使用CONFIG GET命令可以查看持久化数据保存的位置。

> config get dir
1) "dir"
2) "E:\\redis\\redis3.0"
> config get dbfilename
1) "dbfilename"
2) "dump.rdb"

RDB方式优点

  1. RDB是个非常紧凑的文件,保存了redis在某个时间点上的数据集,使得我们可以通过定时备份RDB文件来实现Redis数据库备份和灾难恢复,也可以将其传送到其他的数据中心用于保存。

  2. RDB可以最大化redis的性能,执行RDB持久化时只需要fork一个子进程,并由子进程进行持久化工作,父进程不需要处理任何磁盘I/O操作。

  3. RDB在恢复大数据集时比AOF要快,启动效率要高许多。

  4. RDB文件是经过压缩(可以配置rdbcompression参数以禁用压缩节省CPU占用)的二进制格式,所以占用的空间会小于内存中的数据大小,更加利于传输。

RDB方式缺点

  1. 每次快照持久化都是将内存数据完整写入到磁盘一次,并不是增量的只同步增数据。如果数据量大的话,而且写操作比较多,必然会引起大量的磁盘io操作,可能会严重影响性能。

  2. 快照方式是在一定间隔时间做一次的,所以如果redis意外down掉的话,就会丢失最后一次快照后的所有修改,有一些数据丢失的风险。

  3. client的save或者bgsave命令通知redis做一次快照持久化不推荐。

原因:save操作是在主线程中保存快照的,由于redis是用一个主线程来处理所有 client的请求,这种方式会阻塞所有client请求。所以不推荐使用。

RDB 方式注意事项

Redis模式会运行16个数据库(编号为0---15),在执行保存的过程中无论是SAVE触发还是BGSAVE触发,都是会把所有非空数据库进行保存的。

Append-only file(缩写aof)的方式

默认AOF 方式是关闭的。

RDB方式如果redis 服务意外停止运行后,会将最新写入的数据丢失,在某些严格要求的项目中不是一个可行的方案。此时AOF可以解决这个问题,AOF 方式是在redis 1.1 版本中可用。

AOF 方式是在写入内存数据的同时将操作命令保存到日志文件中。 当你重新启动redis 服务时,它将重新根据AOF以重建状态。这种方式类似于传统数据库服务器的事务日志 。

如果遇到在追加日志的时候遇到意外,可以使用redis-check-aof工具进行日志修复。

因为采用了追加方式,所以AOF会越来越大(这一点又和传统数据库不一样,传统数据库事务日志文件都比较小),因此redis有另外一个机制就是AOF文件重写,当AOF文件达到一个设定的阈值后,会自动启动AOF文件压缩,只保留可以恢复数据的最小指令集。

配置

# 在配置文件中打开AOF
appendonly yes
# aof方式文件名
appendfilename "appendonly.aof"

# 每次执行写入都会执行同步,最安全也最慢,执行write()和fsync()系统调用。
# appendfsync always
# 每秒执行一次同步,默认,执行write()和fsync()系统调用。
appendfsync everysec
# 不主动进行同步操作,而是完全交由操作系统来做(即每30秒一次),最快也最不安全,只执行write()。
# appendfsync no

AOF 持久化原理

  1. 当AOF 持久化开启后,对数据库进行一次更新操作后,更新命令会被追加到aof_buf缓冲区的末尾,然后缓冲区写入到AOF 文件。

  2. AOF文件中记录的内容就是对数据更新操作的指令。这个文件本身就是以文本来记录的。

redis进行了如下操作:

> set 40kuai 40
OK
> get 40kuai 40
(error) ERR wrong number of arguments for 'get' command
> get 40kuai
"40"
> del 40kuai
(integer) 1

下面我们来查看下appendonly.aof文件的内容:

*2
$6
SELECT
$1
0
*3
$3
set
$6
40kuai
$2
40
*2
$3
del
$6
40kuai

分别解释下各个字段的含义:

字符含义
*2 表示2个参数
$6 第一个参数长度为6
SELECT 第一个参数
$1 第二个参数的长度为1
0 第二个参数

注意:这里可以看出 appendonly.aof文件中记录的都是对数据进行操作的命令,对于用户使用GET 进行查询的操作并没有记录。

AOF 重写实现原理

因为AOF持久化是通过记录命令的方式来保存数据库状态的,随着时间的推移AOF文件肯定会逐渐增大,如果不加以控制会对AOF持久化性能以及数据恢复造成影响。

以一个列表为例来说明重写的意义:

> rpush list a b
(integer) 2
> rpush list c
(integer) 3
> lrange list 0 1
1) "a"
2) "b"

根据AOF的原理,上面的操作需要将2条命令追加到appendonly.aof文件当中,其实我们看到list最后的状态是值a,b,c。当使用appendonly.aof文件进行恢复时,要实现最后的状态,需要追加2 条命令,所以在大量内存读写的业务里AOF文件增长的很快。为了解决这个问题,Redis提供了AOF重写功能。

AOF重写就是创建一个新的AOF文件来替换现有的AOF文件,实际上AOF重写并不对现有的旧AOF文件进行操作。当进行重写的时候直接从数据库里去获取list的最新状态,然后在新的AOF文件中直接写一条rpushlist B C D E F命令,从而避免写5条的操作,这样AOF文件的增长速度就会降低,同时容量也不会特别大。

AOF重写程序aof_rewrite函数去完成创建新的AOF文件的任务,但是该函数并不会由Redis主进程去直接调用,而是使用子进程后台去执行(BGREWRITEAOF,该命令其实就是执行aof_rewrite,只不过是由子进程去调用的),这时主进程就会不被阻塞,那么就可以在执行重写的过程中父进程可以继续对外提供响应。整个过程如下:

  • 当重写被触发时父进程调用一个函数,该函数创建一个子进程用于执行BGREWRITEAOF,该子进程创建一个临时文件,然后父进程继续对外提供读写服务。

  • 子进程遍历数据库,将每个键值的最新状态输出到临时文件中,在BGREWRITEAOF过程中,父进程把所有对数据库的更新命令同时写入到AOF缓冲区和AOF重写缓冲区(aof_rewrite_buf_blocks),AOF缓冲区(aof_buf)会继续同步到现有AOF文件中(一般情况下在AOF重写期间不建议把AOF缓冲区的内容同步到现有的AOF文件中,这会降低性能,默认为NO)。

  • AOF重写完成后子进程通知父进程,父进程调用信号处理函数。

  • 信号处理函数会阻塞父进程对外提供读写操作(时间很短,不阻塞就又会出现数据不一致的情况),然后将AOF重写缓冲区的内容写入到新的AOF文件中,最后用新的AOF文件替换现有AOF文件(更名操作)。

# yes : 在日志重写时,不进行命令追加操作,而只是将其放在缓冲区里,避免与命令的追加造成DISK IO上的冲突。
# no : 在日志重写时,命令追加操作照常进行。
no-appendfsync-on-rewrite no
# 当目前的AOF文件大小超过上一次重写时的AOF文件大小的百分之多少时会再次进行重写,如果之前没有重写过,则以启动时的AOF文件大小为依据
auto-aof-rewrite-percentage 100
# 允许重写的最小AOF文件大小
auto-aof-rewrite-min-size 64mb

AOF 方式优点

  1. 该机制可以带来更高的数据安全性,即数据持久性。

  2. 由于该机制对日志文件的写入操作采用的是append模式,因此在写入过程中即使出现宕机现象,也不会破坏日志文件中已经存在的内容。然而如果我们本次操作只是写入了一半数据就出现了系统崩溃问题,不用担心,在Redis下一次启动之前,我们可以通过redis-check-aof工具来帮助我们解决数据一致性的问题。

  3. 如果日志过大,Redis可以自动启用rewrite机制。即Redis以append模式不断的将修改数据写入到老的磁盘文件中,同时Redis还会创建一个新的文件用于记录此期间有哪些修改命令被执行。因此在进行rewrite切换时可以更好的保证数据安全性。

  4. AOF包含一个格式清晰、易于理解的日志文件用于记录所有的修改操作。事实上,也可以通过该文件完成数据的重建。

AOF 方式缺点

  1. 对于相同数量的数据集而言,AOF文件通常要大于RDB文件,持久化文件会变的越来越大。

  2. 根据同步策略的不同,AOF在运行效率上往往会慢于RDB。

其他方式

虚拟内存方式和diskstore方式这里不做说明

Redis 数据类型和抽象

redis 键

Redis的键是二进制安全的,这意味着您可以使用任何二进制序列作为键 。

redis strings

Redis String类型是可以与Redis密钥关联的最简单的值类型。它是Memcached中唯一的数据类型。

使用SETGET命令是我们设置和检索字符串值的方式。请注意,即使密钥与非字符串值相关联,SET也将替换已存在于密钥中的任何现有值。

SET命令有有趣的选项,这是作为附加参数。例如,如果密钥已经存在,我可能会要求SET失败,或者相反,如果密钥已经存在,它只会成功:详情

> set mykey newval nx
(nil)
> set mykey newval xx
OK
# EX seconds - 设置指定的过期时间,以秒为单位。
# PX 毫秒 - 设置指定的过期时间,以毫秒为单位。
# NX - 仅设置密钥(如果密钥尚不存在)。
# XX - 仅设置密钥(如果密钥已存在)。

字符串的操作还有一些其他的命令,如下:

> set counter 100
OK
> incr counter
(integer) 101
> incr counter
(integer) 102
> incrby counter 50
(integer) 152

INCR: 解析字符串值作为整数,以一增加它,最后将获得的值作为新的值。还有其他类似的命令,如INCRBY, DECRDECRBY。在内部,它始终是相同的命令,以稍微不同的方式运作。 (INCR是原子操作,即使是针对相同密钥发布INCR的多个客户端也不会进入竞争状态 )

GETSET: 将键设置为新值,并将旧值作为结果返回 。

在单个命令中设置或检索多个键的值的能力对于减少延迟也是有用的。因此,有MSETMGET命令:

> mset a 10 b 20 c 30
OK
> mget a b c    # 使用MGET时,Redis返回值数组。
1) "10"
2) "20"
3) "30"

EXISTS:返回1或0以表示数据库中是否存在给定键。

DEL:删除键和关联值,无论值是什么。

> set mykey hello
OK
> exists mykey
(integer) 1
> del mykey
(integer) 1
> exists mykey
(integer) 0

可以看到DEL本身如何返回1或0,具体取决于密钥是否被删除(它是否存在)(没有具有该名称的密钥)。

有许多与密钥空间相关的命令,但上面两个是与TYPE命令一起必不可少的命令,它返回存储在指定键中的值的类型:

> set mykey x
OK
> type mykey
string
> del mykey
(integer) 1
> type mykey
none

redis strings 其他命令说明

命令说明
INCR key 将 key 中储存的数字值增一。
INCRBY key num 将 key 所储存的值加上给定的增量值(num)。
DECR key 将 key 中储存的数字值减一。
DECRBY key num key 所储存的值减去给定的减量值。
APPEND key value 如果 key 已经存在并且是一个字符串, APPEND 命令将指定的 value 追加到该 key 原来值的末尾。

 

redis 到期:live时间有限的keys

默认情况下键是没有生存时间的,永不过期,除非使用del来清除键。

设置到期时间

设置到期时间方法入下:

  1. strings类型,SET命令是可以直接通过EX,PX来指定过期时间。

  2. 所有类型都可以使用,EXPIRE、PEXPIRE、EXPIREAT、PEXPIREAT 这四个命令来进行生存时间的设置。

命令说明
EXPIRE KEY #s 将KEY的生存时间设置为#秒
PEXPIRE KEY #ms 将KEY的生存时间设置为#毫秒
EXPIREAT KEY timestamp 将KEY的生存时间设置为UNIX时间戳,单位为秒
PEXPIREAT KEY timestamp 将KEY的生存时间设置为UNIX时间戳,单位为毫秒
TIME 一个包含两个字符串的列表: 第一个字符串是当前时间(以 UNIX 时间戳格式表示),而第二个字符串是当前这一秒钟已经逝去的微秒数。

上面这4个命令只是单位和表现形式上的不同,但实际上EXPIRE、PEXPIRE以及EXPIREAT命令的执行最后都会使用PEXPIREAT来实行。

查看key的到期时间

Key的到期时间可以使用 TTLPTTL来进行查看,分别返回秒和毫秒单位级别。

清除key的到期时间

可以使用PERSIST命令移除一个键的过期时间 。

> set key 100
OK
> EXPIRE key 100
(integer) 1
> get key
"100"
> ttl key
(integer) 92
> PERSIST key
(integer) 1
> ttl key
(integer) -1

到期时间返回值说明

返回值说明
-2 过期且已删除
-1 没有过期时间设置,即永不过期
>0 表示距离过期还有多少秒或者毫秒
posted @ 2018-08-16 16:54  40块钱抓娃娃  阅读(206)  评论(0编辑  收藏  举报