您的位置:首页 > 数据库 > Redis

Redis学习与总结

2017-02-20 14:38 417 查看
Redis将按照以下的的顺序进行总结

Redis
Redis的常用命令
Redis的安装过程
Redis主从复制原理
Redis持久化原理
Redis的哨兵Sentinel机制
Redis的API使用

Redis

Redis是一个开源、支持网络、基于内存、键值对的NoSQL数据库

Redis常用命令

Redis 支持string list hash set sortset 五种数据类型
http://8d9901d5.wiz01.com/share/s/2dCg7l3-1kCv2lEZIt2_gYod0iaUd42pBATf28cVd41LwKTl


Redis安装过程

安装环境:Linux centos
安装版本:redis-3.0.7
安装过程:

下载 redis-3.0.7.tar.gz 并解压

进入解压目录并make,然后可以看到src目录下的可执行命令
redis安装采用主从模式,使用redis的两种持久化方法:快照(RDB文件)与追加式文件(AOF文件);同时采用redis自带哨兵机制以完成主从切换。
大部分的配置默认即可,下面为改动或者添加的部分
 下面是redis.conf中对应改动的部分

#默认采用daemon的方式


daemonize yes


#改变默认的6379端口,防止人为攻击


port
16379


#指定redis的日志文件位置


logfile
/home/stat/redis-3.0.7/logs/redis.log


#指定持久化文件的日志文件


dir
/home/stat/redis-3.0.7/data


#这个只在slave侧的redis.conf中进行设置


slaveof
10.186.150.201
16379


#开启aof持久化方式


appendonly yes

    下面是sentinel.conf中对应改动的部分

#指定sentinel的工作目录


dir
"/home/stat/redis-3.0.7/data"


#指定sentinel监控的master节点及端口


sentinel monitor mymaster
10.186.150.201
16379
2

redis启动:./redis-server ../redis.conf
redis停止:./redis-cli -p 16379 shutdown

其他的查询命令:
./redis-cli -h host_ip -p 16379 (redis服务端口);INFO命令查看当前主机是slave还是master及其他状态
./redis-cli -h host_ip -p 26379(redis sentinel服务端口);INFO  sentinel 查看sentinel哨兵信息;sentinel masters 查看master 节点信息;sentinel slaves mymaster(sentinel.conf制定的名字) 查看slave信息

Redis主从复制原理


配置好slave后,slave与master建立连接,然后发送sync命令. 
无论是第一次连接还是重新连接,master都会启动一个后台进程,将数据库快照保存到文件中,同时master主进程会开始收集新的写命令并缓存. 
后台进程完成写文件后,master就发送文件给slave,slave将文件保存到硬盘上,再加载到内存中, 
接着master就会把缓存的命令转发给slave,后续master将收到的写命令发送给slave. 
如果master同时收到多个slave发来的同步连接命令,master只会启动一个进程来写数据库镜像, 然后发送给所有的slave

Redis持久化原理


Redis有两种持久化的方式:快照(
RDB
文件)和追加式文件(
AOF
文件):

RDB持久化方式会在一个特定的间隔保存那个时间点的一个数据快照。
AOF持久化方式则会记录每一个服务器收到的写操作。在服务启动时,这些记录的操作会逐条执行从而重建出原来的数据。写操作命令记录的格式跟Redis协议一致,以追加的方式进行保存。
Redis的持久化是可以禁用的,就是说你可以让数据的生命周期只存在于服务器的运行时间里。
两种方式的持久化是可以同时存在的,但是当Redis重启时,AOF文件会被优先用于重建数据。
RDB

工作原理
Redis调用fork(),产生一个子进程。
子进程把数据写到一个临时的RDB文件。
当子进程写完新的RDB文件后,把旧的RDB文件替换掉。
优点
RDB文件是一个很简洁的单文件,它保存了某个时间点的Redis数据,很适合用于做备份。你可以设定一个时间点对RDB文件进行归档,这样就能在需要的时候很轻易的把数据恢复到不同的版本。
基于上面所描述的特性,RDB很适合用于灾备。单文件很方便就能传输到远程的服务器上。
RDB的性能很好,需要进行持久化时,主进程会fork一个子进程出来,然后把持久化的工作交给子进程,自己不会有相关的I/O操作。
比起AOF,在数据量比较大的情况下,RDB的启动速度更快。
缺点
RDB容易造成数据的丢失。假设每5分钟保存一次快照,如果Redis因为某些原因不能正常工作,那么从上次产生快照到Redis出现问题这段时间的数据就会丢失了。
RDB使用
fork()
产生子进程进行数据的持久化,如果数据比较大的话可能就会花费点时间,造成Redis停止服务几毫秒。如果数据量很大且CPU性能不是很好的时候,停止服务的时间甚至会到1秒。
保存点(RDB的启用和禁用)

你可以配置保存点,使Redis如果在每N秒后数据发生了M次改变就保存快照文件。例如下面这个保存点配置表示每60秒,如果数据发生了1000次以上的变动,Redis就会自动保存快照文件:
save 60 1000


保存点可以设置多个,Redis的配置文件就默认设置了3个保存点:
# 格式为:save <seconds> <changes># 可以设置多个。
save 900 1 #900秒后至少1个key有变动
save 300 10 #300秒后至少10个key有变动
save 60 10000 #60秒后至少10000个key有变动


如果想禁用快照保存的功能,可以通过注释掉所有"save"配置达到,或者在最后一条"save"配置后添加如下的配置:
save ""


错误处理

默认情况下,如果Redis在后台生成快照的时候失败,那么就会停止接收数据,目的是让用户能知道数据没有持久化成功。但是如果你有其他的方式可以监控到Redis及其持久化的状态,那么可以把这个功能禁止掉。
stop-writes-on-bgsave-error yes


数据压缩

默认Redis会采用
LZF
对数据进行压缩。如果你想节省点CPU的性能,你可以把压缩功能禁用掉,但是数据集就会比没压缩的时候要打。
rdbcompression yes


数据校验

从版本5的RDB的开始,一个
CRC64
的校验码会放在文件的末尾。这样更能保证文件的完整性,但是在保存或者加载文件时会损失一定的性能(大概10%)。如果想追求更高的性能,可以把它禁用掉,这样文件在写入校验码时会用
0
替代,加载的时候看到
0
就会直接跳过校验。
rdbchecksum yes


手动生成快照

Redis提供了两个命令用于手动生成快照。


SAVE

SAVE命令会使用同步的方式生成RDB快照文件,这意味着在这个过程中会阻塞所有其他客户端的请求。因此不建议在生产环境使用这个命令,除非因为某种原因需要去阻止Redis使用子进程进行后台生成快照(例如调用
fork(2)
出错)。


BGSAVE

BGSAVE命令使用后台的方式保存RDB文件,调用此命令后,会立刻返回
OK
返回码。Redis会产生一个子进程进行处理并立刻恢复对客户端的服务。在客户端我们可以使用LASTSAVE命令查看操作是否成功。
127.0.0.1:6379> BGSAVEBackground saving started
127.0.0.1:6379> LASTSAVE
(integer) 1433936394


配置文件里禁用了快照生成功能不影响
SAVE
BGSAVE
命令的效果。


AOF

快照并不是很可靠。如果你的电脑突然宕机了,或者电源断了,又或者不小心杀掉了进程,那么最新的数据就会丢失。而AOF文件则提供了一种更为可靠的持久化方式。每当Redis接受到会修改数据集的命令时,就会把命令追加到AOF文件里,当你重启Redis时,AOF里的命令会被重新执行一次,重建数据。

优点
比RDB可靠。你可以制定不同的fsync策略:不进行fsync、每秒fsync一次和每次查询进行fsync。默认是每秒fsync一次。这意味着你最多丢失一秒钟的数据。
AOF日志文件是一个纯追加的文件。就算是遇到突然停电的情况,也不会出现日志的定位或者损坏问题。甚至如果因为某些原因(例如磁盘满了)命令只写了一半到日志文件里,我们也可以用
redis-check-aof
这个工具很简单的进行修复。
当AOF文件太大时,Redis会自动在后台进行重写。重写很安全,因为重写是在一个新的文件上进行,同时Redis会继续往旧的文件追加数据。新文件上会写入能重建当前数据集的最小操作命令的集合。当新文件重写完,Redis会把新旧文件进行切换,然后开始把数据写到新文件上。
AOF把操作命令以简单易懂的格式一条接一条的保存在文件里,很容易导出来用于恢复数据。例如我们不小心
FLUSHALL
命令把所有数据刷掉了,只要文件没有被重写,我们可以把服务停掉,把最后那条命令删掉,然后重启服务,这样就能把被刷掉的数据恢复回来。


缺点

在相同的数据集下,AOF文件的大小一般会比RDB文件大。
在某些fsync策略下,AOF的速度会比RDB慢。通常fsync设置为每秒一次就能获得比较高的性能,而在禁止fsync的情况下速度可以达到RDB的水平。
在过去曾经发现一些很罕见的BUG导致使用AOF重建的数据跟原数据不一致的问题。


启用AOF

把配置项
appendonly
设为
yes

appendonly yes


文件路径和名称

# 文件存放目录,与RDB共用。默认为当前工作目录。dir ./

# 默认文件名为appendonly.aof
appendfilename "appendonly.aof"


可靠性

你可以配置Redis调用fsync的频率,有三个选项:
每当有新命令追加到AOF的时候调用fsync。速度最慢,但是最安全。
每秒fsync一次。速度快(2.4版本跟快照方式速度差不多),安全性不错(最多丢失1秒的数据)。
从不fsync,交由系统去处理。这个方式速度最快,但是安全性一般。

推荐使用每秒fsync一次的方式(默认的方式),因为它速度快,安全性也不错。相关配置如下:
# appendfsync alwaysappendfsync everysec
# appendfsync no


日志重写(Rewrite机制)

随着写操作的不断增加,AOF文件会越来越大。例如你递增一个计数器100次,那么最终结果就是数据集里的计数器的值为最终的递增结果,但是AOF文件里却会把这100次操作完整的记录下来。而事实上要恢复这个记录,只需要1个命令就行了,也就是说AOF文件里那100条命令其实可以精简为1条。所以Redis支持这样一个功能:在不中断服务的情况下在后台重建AOF文件。

工作原理如下:
Redis调用fork(),产生一个子进程。
子进程把新的AOF写到一个临时文件里。
主进程持续把新的变动写到内存里的buffer,同时也会把这些新的变动写到旧的AOF里,这样即使重写失败也能保证数据的安全。
当子进程完成文件的重写后,主进程会获得一个信号,然后把内存里的buffer追加到子进程生成的那个新AOF里。
Redis

我们可以通过配置设置日志重写的条件:
# Redis会记住自从上一次重写后AOF文件的大小(如果自Redis启动后还没重写过,则记住启动时使用的AOF文件的大小)。# 如果当前的文件大小比起记住的那个大小超过指定的百分比,则会触发重写。# 同时需要设置一个文件大小最小值,只有大于这个值文件才会重写,以防文件很小,但是已经达到百分比的情况。

auto-aof-rewrite-percentage 100

auto-aof-rewrite-min-size 64mb


要禁用自动的日志重写功能,我们可以把百分比设置为0:
auto-aof-rewrite-percentage 0


Redis 2.4以上才可以自动进行日志重写,之前的版本需要手动运行BGREWRITEAOF这个命令。


Redis数据恢复顺序

当redis服务器挂掉时,重启时将按以下优先级恢复数据到内存种:

1. 如果只配置了AOF,重启时加载AOF文件恢复数据.

2. 如果同时配置了RBD和AOF,启动时只加载AOF文件恢复数据.

3. 如果只配置了㻾DB,启动时将加载dump文件恢复数据.


数据损坏修复

如果因为某些原因(例如服务器崩溃)AOF文件损坏了,导致Redis加载不了,可以通过以下方式进行修复:
备份AOF文件。

使用
redis-check-aof
命令修复原始的AOF文件:
$ redis-check-aof --fix


可以使用
diff -u
命令看下两个文件的差异。
使用修复过的文件重启Redis服务。


从RDB切换到AOF

这里只说Redis >= 2.2版本的方式:
备份一个最新的
dump.rdb
的文件,并把备份文件放在一个安全的地方。

运行以下两条命令:
$ redis-cli config set appendonly yes
$ redis-cli config set save ""


确保数据跟切换前一致。

确保数据正确的写到AOF文件里。

第二条命令是用来禁用RDB的持久化方式,但是这不是必须的,因为你可以同时启用两种持久化方式。

记得对配置文件
redis.conf
进行编辑启用AOF,因为命令行方式修改配置在重启Redis后就会失效。


备份


建议的备份方法

创建一个定时任务,每小时和每天创建一个快照,保存在不同的文件夹里。
定时任务运行时,把太旧的文件进行删除。例如只保留48小时的按小时创建的快照和一到两个月的按天创建的快照。
每天确保一次把快照文件传输到数据中心外的地方进行保存,至少不能保存在Redis服务所在的服务器

Redis哨兵机制

Sentinel(哨兵)是用于监控redis集群中Master状态的工具

Sentinel作用


Master状态检测
如果Master异常,则会进行Master-Slave切换,将其中一个Slave作为Master,将之前的Master作为Slave
Master-Slave切换后,master_redis.conf、slave_redis.conf和sentinel.conf的内容都会发生改变,即master_redis.conf中会多一行slaveof的配置,sentinel.conf的监控目标会随之调换

Sentinel工作方式

每个Sentinel以每秒钟一次的频率向它所知的Master,Slave以及其他 Sentinel 实例发送一个 PING 命令
如果一个实例(instance)距离最后一次有效回复 PING 命令的时间超过 down-after-milliseconds 选项所指定的值, 则这个实例会被 Sentinel 标记为主观下线
如果一个Master被标记为主观下线,则正在监视这个Master的所有 Sentinel 要以每秒一次的频率确认Master的确进入了主观下线状态

当有足够数量的 Sentinel(大于等于配置文件指定的值)在指定的时间范围内确认Master的确进入了主观下线状态, 则Master会被标记为客观下线
在一般情况下, 每个 Sentinel 会以每 10 秒一次的频率向它已知的所有Master,Slave发送 INFO 命令

当Master被 Sentinel 标记为客观下线时,Sentinel 向下线的 Master 的所有 Slave 发送 INFO 命令的频率会从 10 秒一次改为每秒一次

若没有足够数量的 Sentinel 同意 Master 已经下线, Master 的主观下线状态就会被移除

若 Master 重新向 Sentinel 的 PING 命令返回有效回复, Master 的主观下线状态就会被移除

备注
主观下线:Subjectively Down,简称 SDOWN,指的是当前 Sentinel 实例对某个redis服务器做出的下线判断
客观下线:Objectively Down, 简称 ODOWN,指的是多个 Sentinel 实例在对Master Server做出 SDOWN 判断,并且通过 SENTINEL is-master-down-by-addr 命令互相交流之后,得出的Master
Server下线判断,然后开启failover.
SDOWN适合于Master和Slave,只要一个 Sentinel 发现Master进入了ODOWN, 这个 Sentinel 就可能会被其他 Sentinel 推选出, 并对下线的主服务器执行自动故障迁移操作。
ODOWN只适用于Master,对于Slave的 Redis 实例,Sentinel 在将它们判断为下线前不需要进行协商, 所以Slave的 Sentinel 永远不会达到ODOWN。
注意点

首次启动时,必须先启动Master

Sentinel 只在 server 端做主从切换,app端要自己开发(例如Jedis库的SentinelJedis,能够监控Sentinel的状态)

若Master已经被判定为下线,Sentinel已经选择了新的Master,也已经将old Master改成Slave,但是还没有将其改成new Master。若此时重启old Master,则Redis集群将处于无Master状态,此时只能手动修改配置文件,然后重新启动集群

Redis API使用

Redis的使用需要用到API,maven依赖如下

<dependency>

<groupId>redis.clients</groupId>

<artifactId>jedis</artifactId>

<version>2.7.3</version>

</dependency>


Redis的使用主要以下三种:

直接使用Redis的接口Jedis
使用Redis资源池的接口JedisPool
资源池维护一个资源连接池,jedis实例可以动态的从中获取连接资源

使用Redis 集群的接口JedisCluster
JedisCluster是jedis封装的关于redis cluster操作的class;

JedisCluster里主要有两个成员变量:maxRedirections和connectionHandler
JedisCluster会从connectionHandler基于key找出对应的SLOTS和NODES,并找出对应的JedisPool对象
从JedisPool对象中找出可用的Jedis实例,执行Jedis的对应操作

JedisPool的使用
JedisPool的配置

JedisPoolConfig config = new JedisPoolConfig();

String host = Config.getM_strRedisIp();

int port = Config.getM_nRedisPort();

config.setMaxTotal(MAX_ACTIVE);

config.setMaxIdle(MAX_IDLE);

config.setMaxWaitMillis(MAX_WAIT);

config.setTestOnBorrow(TEST_ON_BORROW);

jedisPool = new JedisPool(config, host, port, TIMEOUT);


JedisPool之Jedis实例调用

Jedis jedis = jedisPool.getResource();


JedisCluster的使用

#设置集群的节点

Set<HostAndPort> nodes = new HashSet<HostAndPort>();

String redisCluster = Config.getM_strRedisCluster();

String[] ipPorts = redisCluster.split(",");

for (String ipPort : ipPorts)

{

String ip = ipPort.split(":")[0];

String port = ipPort.split(":")[1];

nodes.add(new HostAndPort(ip, Integer.parseInt(port)));

}

#配置config

JedisPoolConfig poolConfig = new JedisPoolConfig();

poolConfig.setMaxIdle(5);

poolConfig.setMaxTotal(20);

// 在borrow一个jedis实例时,是否提前进行validate操作;如果为true,则得到的jedis实例均是可用的;

poolConfig.setTestOnBorrow(true);

#设置超时时间

int timeout = 5000;

#创建jedisCluster

JedisCluster jedisCluster = new JedisCluster(nodes, timeout, poolConfig);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  redis