成为架构师是很多程序员的梦想,Redis,这个非常流行的框架,里面却蕴含了很多优秀的架构设计,前面我们已经讲了很多Redis的相关知识,就如冰山一角,很多知识还需要我们进一步进行挖掘。

一、复制集

问了能够保证redis数据库中的数据不会因为在服务器出现故障,导致数据丢失,现在需要对redis数据库进行主从设置。保证主服务器数据丢失,可以通过从服务器对数据进行恢复

REmote DIctionary Server(Redis) 是一个由Salvatore
Sanfilippo写的key-value存储系统。

图片 1

1、安装

对redis数据库的主从配置只需在配置文件中配置参数即可。首先需要对主从服务器选取端口号,一个主数据库实例配置6379端口,两个从数据库实例配置6380和6381端口。在配置主从实例时,只需在从实例配置slaveof
<masterip> <masterport> 参数即可。

安装redis实例:

1、从官方网站下载安装包redis-3.0.6.tar.gz

2、对文件进行解压

  tar xzvf redis-3.0.6.tar.gz

3、redis的运行环境的工具安装

  yum install gcc
  yum install gcc-c++

4、进入安装文件

*  cd redis-3.0.6*

5、编译

*  make*

6、安装到指定目录

make PREFIX=/usr/local/redis01/redis install

启动实例:

redis-server    ./6379.conf

关闭实例:

redis-cli -p 6379 shutdown

Redis是一个开源的使用ANSI
C语言编写、遵守BSD协议、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。

今天我们来讲一讲,Redis是如何做主从同步的。我认识的很多Java程序员,都能熟练使用Redis,但是对于一些基础的知识,往往不够重视,我以前也是如此,直到后来去了一个创业公司,什么东西都是从零开始,才慢慢捡回来这些基础的理论。

2、配置

配置参数如下:

daemonize yes    //是否后台执行redis实例

pidfile /usr/local/redis01/redis/redis.pid   //  线程文件的存放位置

port 6379     //实例运行的端口号

logfile “/usr/local/redis01/redis/6379.log”       //实例运行时的记录日志

save 900 1      //没N秒执行M次数据操作,就会快照一次
save 300 10  //……….
save 60 10000       //………..

dbfilename dump.rdb    //快照执行时生成的文件

dir /usr/local/redis01/redis/    //快找执行时,生成的文件位置

slaveof <masterip> <masterport> 
 //主从集群时,只需在从实例的配置文件中配置主实例的ip和端口

slave-read-only yes     //从实例是否为制度模式

timeout 300    //当
客户端闲置多长时间后关闭连接,如果指定为0,表示关闭该功能

maxclients 128   
 //设置同一时间最大客户端连接数,默认无限制,Redis可以同时打开的客户端连接数为Redis进程可以打开的最大文件描述符数,如果设置
maxclients
0,表示不作限制。当客户端连接数到达限制时,Redis会关闭新的连接并向客户端返回max
number of clients reached错误信息

maxmemory <bytes>   
//指定Redis最大内存限制,Redis在启动时会把数据加载到内存中,达到最大内存后,Redis会先尝试清除已到期或即将到期的Key,当此方法处理
后,仍然到达最大内存设置,将无法再进行写入操作,但仍然可以进行读取操作。Redis新的vm机制,会把Key存放内存,Value会存放在swap区

主从实例的分配:

主实例   

 

创建目录6379         mkdir -p /usr/local/redis/6379

将bin下的redis.conf文件复制到6379目录下,并改名为6379.conf             
      scp redis.conf    /usr/local/redis/6379/redis.conf             
mv  redis.conf        6379.conf

从实例

创建目录6380         mkdir -p /usr/local/redis/6380

将bin下的redis.conf文件复制到6379目录下,并改名为6380.conf             
        scp redis.conf    /usr/local/redis/6380/redis.conf         
  mv  redis.conf        6380.conf

创建目录6381         mkdir -p /usr/local/redis/6381

将bin下的redis.conf文件复制到6381目录下                    scp
redis.conf    /usr/local/redis/6381/redis.conf       mv  redis.conf     
  6381.conf

 

查看redis主从配置:

info replication

Redis 与其他 key – value 缓存产品有以下三个特点:

对于一些没有做过互联网的人来说,可能还不知道如何进行为什么需要进行主从同步,在分布式系统设计中,我们需要避免单点问题,也就是说即便是Redis的某台机器挂了,也不能影响到业务的正常使用。

3、复制集的原理

主从复制集的同步分为两步执行,初始同步和增量同步。

全量同步:

在初次开启主从复制集,从数据库会向主数据库发送SYNC命令,主数据收到命令后,开支执行快照操作,执行结束,会将快照和缓存中的操作全部发送给从数据库。再次期间主从数据库都会继续接收来自客户端的请求。在初始同步结束,会进入下一阶段,增量同步。

增量同步:

  1、在初始同步阶段,从数据库就会存储主数据库的ID,每个运行实例都有一个唯一的ID作为标识。

  2、在主数据库将数据同步到从数据库的同时,会将该操作存入队列,并记录下该操作在队列的偏移量。

  3、从数据库会将该操作的偏移量也会记录在本地。

  4、一旦出现主从重连,从数据库会将主数据库的ID与命令偏移量一并交给主数据库。通过ID来判断该从数据库是否是自己的从数据库。如果不是返回错误信息。如果是,需要判断是否要执行增量同步还是全量同步,如果该命令的偏移量在主数据库的队列中,可以将队列中的命令取出执行增量同步。如果该命令偏移量没有存储在队列中,需要执行全量同步。

挤压队列:

  挤压队列是一个固定长度的队列,队列的长度决定的主从断掉后,需要多长时间可以实现全量同步。队列越长允许主从重连执行增量同步的时间就会越长。repl-backlog-size来控制队列大小。

  • Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用。
  • Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储。
  • Redis支持数据的备份,即master-slave模式的数据备份。

    Redis 优势

    • 性能极高 – Redis能读的速度是110000次/s,写的速度是81000次/s 。
    • 丰富的数据类型 – Redis支持二进制案例的 Strings, Lists, Hashes,
      Sets 及 Ordered Sets 数据类型操作。
    • 原子 –
      Redis的所有操作都是原子性的,同时Redis还支持对几个操作全并后的原子性执行。
    • 丰富的特性 – Redis还支持 publish/subscribe, 通知, key
      过期等等特性。

    Redis与其他key-value存储有什么不同?

    • Redis有着更为复杂的数据结构并且提供对他们的原子性操作,这是一个不同于其他数据库的进化路径。Redis的数据类型都是基于基本数据结构的同时对程序员透明,无需进行额外的抽象。

    • Redis运行在内存中但是可以持久化到磁盘,所以在对不同数据集进行高速读写时需要权衡内存,应为数据量不能大于硬件内存。在内存数据库方面的另一个优点是,相比在磁盘上相同的复杂的数据结构,在内存中操作起来非常简单,这样Redis可以做很多内部复杂性很强的事情。同时,在磁盘格式方面他们是紧凑的以追加的方式产生的,因为他们并不需要进行随机访问。 

可能有人会说,Redis不就是个缓存么?挂了就挂了呗,大不了直接读数据库呗,然而数据库是读写磁盘,而Redis是读写内存,两者天生IO的效率就差很大,如果大面积的缓存失效,会大大增加数据库的压力,导致服务雪崩。所以,在实际应用中,Redis的多机部署非常重要,多台机器,自然就会涉及到数据同步,今天我们来谈一谈当中的主从同步模式。

4、读写分离

  为了减轻客户端访问redis数据库的压力,可以通过主从数据库共同分担压力。为了保证数据的一致性,可以只有主数据库提供写服务,而主从可以同时读服务。

【聊聊redis持久化 – RDB】

增量同步

5、故障恢复

  在主数据库出现崩溃时,可以手动的将从数据库设置为主数据库,命令为
SLAVEOF  NO  ONE。

  在重启主数据库后,将主数据库设置为新的主数据库的从数据库,命令为SLAVEOF

RDB方式,是将redis某一时刻的数据持久化到磁盘中,是一种快照式的持久化方法。

Redis增量同步,也叫指令同步,就是从库按照顺序,重放在主库中进行的指令。就像我们小时候在电视上看到的象棋解说,参赛选手进行什么操作,他们就进行同样的操作。Redis会把指令存放在一个环形队列当中,为什么要放一个环形队列呢?因为内存的容量毕竟有限,如果备机一直起不来,不可能把所有的内存都去存指令,也就是说,如果备机一直未同步,指令可能会被覆盖掉。

二、哨兵模式

  哨兵模式只不过是为主从复制集添加监控,并在出现故障时能够,自动的将故障转移,保证系统的正常运行。

redis在进行数据持久化的过程中,会先将数据写入到一个临时文件中,待持久化过程都结束了,才会用这个临时文件替换上次持久化好的文件。正是这种特性,让我们可以随时来进行备份,因为快照文件总是完整可用的。

图片 2

1、结构图

  图片 3

在哨兵模式下,哨兵不仅可以监控主从数据库,也可以监控其他哨兵的运行情况。如果主数据库下线,哨兵会在从数据库中找出一个转换为主数据库。其实哨兵只是一个进程,主要用来实现监控和故障转移。

对于RDB方式,redis会单独创建(fork)一个子进程来进行持久化,而主进程是不会进行任何IO操作的,这样就确保了redis极高的性能。

如果指令被覆盖掉了,那么肯定增量同步就不行了,这个时候只好寄出我们的杀器,全量同步。

2、哨兵模式搭建

1、创建哨兵目录

  mkdir  /usr/local/redis/sentinel6382

2、复制bin目录下的sentinel.conf文件到6382目录下

  scp  sentinel.conf   /usr/local/redis/sentinel6382

3、修改sentinel.conf配置文件

  sentinel   monitor  mymaster  ip port   number

  mymaster为需要监控的主数据库的名字  ip为主数据库的地址
port为主数据库占用的端口 number为在主数据库宕机后,超过number票即可将从数据库选为主数据库。在哨兵配置文件中只是配置了主数据库的基本信息,没有配置从数据库的基本信息,是因为在与主数据库取得联系后,主数据库会返回给哨兵其他从数据库的基本信息,无需配置。

  sentinel  down-after-milliseconds   6000

  6000表示哨兵多长时间,进行一次数据库的监控,用以发现实例是否正常运行。单位为毫秒,如果大于1秒就以1秒为间隔,如果小于1秒就以实际时间为间隔。

4、搭建主从数据库,由于主从数据库的搭建在前一接已经介绍,本节不再详细介绍

5、启动哨兵进程

  redis-sentinel   sentinel.conf

6、启动主从数据库实例

如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那RDB方式要比AOF方式更加的高效。

全量同步

3、哨兵的原理

  哨兵的运行机制主要分为两步走:建立监控网,故障恢复。

  建立监控网:

  在哨兵初次运行时,会通过INFO指令向主数据库发送信息,主数据库会将自己和从数据库的基本信息返回给哨兵。此后,每个10秒会向哨兵所掌握的主从数据库发送INFO命令,获取数据库的基本信息,查看主数据库是否发送转移,数据库的基本信息是否有更新。

  哨兵向主从数据库的_sentinel_:hello频道发送自己所掌握的主从数据库和哨兵的基本信息,其他哨兵会接收到该信息,并对信息做出判断,查看与自己所掌握的信息是否一致。如是否有新的哨兵加入,如果有,需要将新的哨兵基本信息加入本地列表。此后哨兵会每个2秒向频道发送一次所掌握的复制集信息。

  哨兵在掌握了主从数据库的基本信息后,每隔1秒会向主从数据库发送PING指令,用以监控数据库是否正常运行。

  故障恢复:

  哨兵发送PING指令到数据库,在指定的时间内没返回响应,那么哨兵就会认为该数据库主观下线,如果是主数据库,同时会向其他哨兵发送指令,询问其他哨兵是否认为该数据库下线,如果达到一定数量的哨兵认为该数据库下线,哨兵会认为数据库客观下线。

  在发现主数据库客观下线后,哨兵A会向其他哨兵推荐自己为零头哨兵,如果其他哨兵没有选举其他领头哨兵,则会同意A为零头哨兵。如果发现超过一半或者一定数量的哨兵选举A为领头哨兵,则A就会成为领头哨兵。当有多个哨兵同时参选领头哨兵,并没有一个哨兵当选时,需要等待一段时间重新发去参选请求。

  在选出领头哨兵后,会选择优先级高的从数据库为主数据库。如果有多个数据库为相同优先级,需要通过复制队列的名利偏移量来判断。

虽然RDB有不少优点,但它的缺点也是不容忽视的。如果你对数据的完整性非常敏感,那么RDB方式就不太适合你,因为即使你每5分钟都持久化一次,当redis故障时,仍然会有近5分钟的数据丢失。所以,redis还提供了另一种持久化方式,那就是AOF。

Redis全量同步,又称快照同步。可能有些人不太理解快照的意思,快照,就跟照片一样,记录着在某一个时间点所有键值状态。在Redis中,获取一个快照的命令并不难,我们可以手动创建一个快照,也可以通过配置,后台根据相关规则创建快照。

【聊聊redis持久化 – AOF】

在Redis中,我们可以通过save命令,就可以创建快照,因为Redis是单进程的,使用save命令会影响性能,所以通常我们会使用bgsave。

AOF,英文是Append Only File,即只允许追加不允许改写的文件。

图片 4

如前面介绍的,AOF方式是将执行过的写指令记录下来,在数据恢复时按照从前到后的顺序再将指令都执行一遍,就这么简单。

在redis.conf中,有着自动保存的配置,上述是Redis的默认配置,说的是在900秒内,如果有1个key变更,或者300秒内,有300个key变更,或者60秒内,有1个key变更,就会后台出发生成快照功能。

我们通过配置redis.conf中的appendonly yes就可以打开AOF功能。如果有写操作(如SET等),redis就会被追加到AOF文件的末尾。

总结

默认的AOF持久化策略是每秒钟fsync一次(fsync是指把缓存中的写指令记录到磁盘中),因为在这种情况下,redis仍然可以保持很好的处理性能,即使redis故障,也只会丢失最近1秒钟的数据。

成为架构师是很多程序员的梦想,其实随着经验的增长,只要多总结,你就会发现,很多系统的设计都是相通的,大部分系统的架构设计都是这种多机同步都是这种增量同步+快照的模型,多思考,多比较,相信每个人都能成为架构师。

如果在追加日志时,恰好遇到磁盘空间满、inode满或断电等情况导致日志写入不完整,也没有关系,redis提供了redis-check-aof工具,可以用来进行日志修复。

因为采用了追加方式,如果不做任何处理的话,AOF文件会变得越来越大,为此,redis提供了AOF文件重写(rewrite)机制,即当AOF文件的大小超过所设定的阈值时,redis就会启动AOF文件的内容压缩,只保留可以恢复数据的最小指令集。举个例子或许更形象,假如我们调用了100次INCR指令,在AOF文件中就要存储100条指令,但这明显是很低效的,完全可以把这100条指令合并成一条SET指令,这就是重写机制的原理。

在进行AOF重写时,仍然是采用先写临时文件,全部完成后再替换的流程,所以断电、磁盘满等问题都不会影响AOF文件的可用性,这点大家可以放心。

AOF方式的另一个好处,我们通过一个“场景再现”来说明。某同学在操作redis时,不小心执行了FLUSHALL,导致redis内存中的数据全部被清空了,这是很悲剧的事情。不过这也不是世界末日,只要redis配置了AOF持久化方式,且AOF文件还没有被重写(rewrite),我们就可以用最快的速度暂停redis并编辑AOF文件,将最后一行的FLUSHALL命令删除,然后重启redis,就可以恢复redis的所有数据到FLUSHALL之前的状态了。是不是很神奇,这就是AOF持久化方式的好处之一。但是如果AOF文件已经被重写了,那就无法通过这种方法来恢复数据了。

虽然优点多多,但AOF方式也同样存在缺陷,比如在同样数据规模的情况下,AOF文件要比RDB文件的体积大。而且,AOF方式的恢复速度也要慢于RDB方式。

如果你直接执行BGREWRITEAOF命令,那么redis会生成一个全新的AOF文件,其中便包括了可以恢复现有数据的最少的命令集。

如果运气比较差,AOF文件出现了被写坏的情况,也不必过分担忧,redis并不会贸然加载这个有问题的AOF文件,而是报错退出。这时可以通过以下步骤来修复出错的文件:

1.备份被写坏的AOF文件 2.运行redis-check-aof –fix进行修复 3.用diff -u来看下两个文件的差异,确认问题点 4.重启redis,加载修复后的AOF文件

【聊聊redis持久化 – AOF重写】

AOF重写的内部运行原理,我们有必要了解一下。

在重写即将开始之际,redis会创建(fork)一个“重写子进程”,这个子进程会首先读取现有的AOF文件,并将其包含的指令进行分析压缩并写入到一个临时文件中。

与此同时,主工作进程会将新接收到的写指令一边累积到内存缓冲区中,一边继续写入到原有的AOF文件中,这样做是保证原有的AOF文件的可用性,避免在重写过程中出现意外。

当“重写子进程”完成重写工作后,它会给父进程发一个信号,父进程收到信号后就会将内存中缓存的写指令追加到新AOF文件中。

当追加结束后,redis就会用新AOF文件来代替旧AOF文件,之后再有新的写指令,就都会追加到新的AOF文件中了。

【聊聊redis持久化 – 如何选择RDB和AOF】

对于我们应该选择RDB还是AOF,官方的建议是两个同时使用。这样可以提供更可靠的持久化方案。

【聊聊主从 – 用法】

像MySQL一样,redis是支持主从同步的,而且也支持一主多从以及多级从结构。

主从结构,一是为了纯粹的冗余备份,二是为了提升读性能,比如很消耗性能的SORT就可以由从服务器来承担。

redis的主从同步是异步进行的,这意味着主从同步不会影响主逻辑,也不会降低redis的处理性能。

主从架构中,可以考虑关闭主服务器的数据持久化功能,只让从服务器进行持久化,这样可以提高主服务器的处理性能。

在主从架构中,从服务器通常被设置为只读模式,这样可以避免从服务器的数据被误修改。但是从服务器仍然可以接受CONFIG等指令,所以还是不应该将从服务器直接暴露到不安全的网络环境中。如果必须如此,那可以考虑给重要指令进行重命名,来避免命令被外人误执行。

【聊聊主从 – 同步原理】

从服务器会向主服务器发出SYNC指令,当主服务器接到此命令后,就会调用BGSAVE指令来创建一个子进程专门进行数据持久化工作,也就是将主服务器的数据写入RDB文件中。在数据持久化期间,主服务器将执行的写指令都缓存在内存中。

在BGSAVE指令执行完成后,主服务器会将持久化好的RDB文件发送给从服务器,从服务器接到此文件后会将其存储到磁盘上,然后再将其读取到内存中。这个动作完成后,主服务器会将这段时间缓存的写指令再以redis协议的格式发送给从服务器。

另外,要说的一点是,即使有多个从服务器同时发来SYNC指令,主服务器也只会执行一次BGSAVE,然后把持久化好的RDB文件发给多个下游。在redis2.8版本之前,如果从服务器与主服务器因某些原因断开连接的话,都会进行一次主从之间的全量的数据同步;而在2.8版本之后,redis支持了效率更高的增量同步策略,这大大降低了连接断开的恢复成本。

主服务器会在内存中维护一个缓冲区,缓冲区中存储着将要发给从服务器的内容。从服务器在与主服务器出现网络瞬断之后,从服务器会尝试再次与主服务器连接,一旦连接成功,从服务器就会把“希望同步的主服务器ID”和“希望请求的数据的偏移位置(replication offset)”发送出去。主服务器接收到这样的同步请求后,首先会验证主服务器ID是否和自己的ID匹配,其次会检查“请求的偏移位置”是否存在于自己的缓冲区中,如果两者都满足的话,主服务器就会向从服务器发送增量内容。

增量同步功能,需要服务器端支持全新的PSYNC指令。这个指令,只有在redis-2.8之后才具有。

【聊聊redis的事务处理】

众所周知,事务是指“一个完整的动作,要么全部执行,要么什么也没有做”。

在聊redis事务处理之前,要先和大家介绍四个redis指令,即MULTI、EXEC、DISCARD、WATCH。这四个指令构成了redis事务处理的基础。

1.MULTI用来组装一个事务; 2.EXEC用来执行一个事务; 3.DISCARD用来取消一个事务; 4.WATCH用来监视一些key,一旦这些key在事务执行之前被改变,则取消事务的执行。

常用命令

redis的常用命令主要分为两个方面、一个是键值相关命令、一个是服务器相关命令

1、键值相关命令

      keys * 取出当前所有的key

      exists name 查看n是否有name这个key

      del name 删除key name

      expire confirm 100 设置confirm这个key100秒过期

      ttl confirm 获取confirm 这个key的有效时长

      select 0 选择到0数据库 redis默认的数据库是0~15一共16个数据库

      move confirm 1
将当前数据库中的key移动到其他的数据库中,这里就是把confire这个key从当前数据库中移动到1中

      persist confirm 移除confirm这个key的过期时间

      randomkey 随机返回数据库里面的一个key

      rename key2 key3 重命名key2 为key3

      type key2 返回key的数据类型

2、服务器相关命令

      ping PONG返回响应是否连接成功

      echo 在命令行打印一些内容

      select 0~15 编号的数据库

      quit  /exit 退出客户端

      dbsize 返回当前数据库中所有key的数量

      info 返回redis的相关信息

      config get dir/* 实时传储收到的请求

      flushdb 删除当前选择数据库中的所有key

      flushall 删除所有数据库中的数据库

发表评论

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

相关文章