Redis基础

本篇博客整理了一些关于redis基础相关的内容,主要会从一下几个方面展开, 其中有很多命令,其实也很重要,后期代码控制redis时,api基本上约等于命令

  • 常识
  • redis的五大数据类型
  • 常用命令
  • RDB 与 AOF
  • redis的事务
  • 主从复制-读写分离

常识补充

点击进入redis官网

redis简介(REmote dIctionary Server 远程字典服务器):

  • 是完全开源免费的,由C语言编写的,一个高性能的(key/value)分布式内存数据库,基于内存运行, 并支持持久化的Nosql数据库,也被称为" 数据结构服务器 "

提前剧透,redis关于key-value的三大特点:

  1. redis是支持持久化的! 我们可以控制 数据 何时,用何种方式 保存到磁盘中,每次重启再次加载该文件,可以完成数据恢复
  2. redis不单单支持简单的key-value数据类型,同时还可以提供list,set,hash,zset等数据类型的存储
  3. 支持数据的备份,mater-slave模式,即,当下时髦的主从复制读写分离

应用场景:

  • 内存存储的持久化: 虽然redis是单线程实现的,但是支持异步将数据持久化到硬盘上,同时不影响继续服务
  • 发布订阅
  • 定时器,计时器: 我们可以把这个特性用到发短信的服务中,每次发送完短信后,就进入倒计时,在指定的时间内,决绝发送第二次,有效的缓解短信服务的压力,节流
  • 取出最新的N个数据的操作: 比如新浪微博的评论系统,他要展示最新的10条评论,就是把最新的10条评论的id放到redis的list里面

Redis五大数据类型

String:等同于java中的,Map<String,String>

  • string 是redis里面的最基本的数据类型,一个key对应一个value
  • string 是二进制安全的,意味着,就算我们通过加密算法把图片或者序列化的对象set给redis,它帮我们安全的存储
  • string的最大内存值 512M

常用命令:

常用命令 命令
添加一对kv set key value
添加多对kv(可覆盖) mset key value key value....
添加多对kv(不可覆盖,只要有一个已存在,全部取消) msetnx key value key value....
获取 get value
获取多对kv mget key key...
删除 del key
在末尾追加 append key value
查询v的长度 strlen key
给数值类型的v加/减1 incr/decr key
给数值类型增加/减少指定大小的值 incrby/decrby key value
获取v的长度 getrange key
在指定位置添加指定值(中间默认用空格补全) setrange key offset value
添加指定生命周期的kv setex key seconds value
如果不存在则添加 setnx key value
获取旧值,设置新值 setget key value

Hash:等同于java中的:Map<String,Map<String,String>>

  • redis的hash是一个键值对的集合 Map(string, Object)
  • redis的hash是一个string类型的field和value的映射表,特别适合存储对象

划重点!!!特别适合存储对象

同样,hash相关的指令,以 h 开头

作用 命令
添加单个 hset key field value
获取单个 hget key field
一次性添加多个键值 hmset key field1 value1 field2 value2 ...
一次性获取多个 hmget
获取所有键值 hgetall key
删除 hdel
获取键值对的个数 hlen
检查是否包含某个字段 hget key field
查看所有key hkeys
给某个数值类型(否则报错)的值增加指定整数值 hincrby key field increment
给某个数字类型值,增加指定浮点类型值 hincrbyfloat key field increment
如果不存在则添加 hsetnx

list:等同于java中的Map<String,List<String>>

  • redis的list是一个简单的字符串类型的列表,从功能上看, 它就像是栈和队列结婚后的产物 首先: 它会按照我们插入的顺序排序, 然后我们可以从他的头部添加/获取元素,也可以从它的尾部添加/获取元素, (底层实际上是个链表)

list中有比较容易混淆的左右之分,我是把整个list看成一个两边相同的管子,如果是L开头的操作,就想象用左手把这个管子竖起来(我取名字叫左压栈),如果是R开头,就想象是右手把这个管子竖起来,这样就不会混淆取出来的值到底是谁

list相关的指令,开头全部是 l 意味list

常用命令 命令
左压栈 lpush key v1 v2 v3 v4...
右压栈 rpush key v1 v2 ...
查看里面的元素 lrange key start offset
左弹栈 lpop key
右弹栈 rpop key
按照索引查找 lindex key index
查看长度 llen key
删除几个几 lrem key 数量 value
指定开始和结束的位置截取,再赋值给key ltrim key start offset
右出栈左压栈,把resoure的左后一个,压倒dest的第一个 rpoplpush resource destination
重置指定索引的值 lset key index value
在指定元素前/后插入指定元素 linsert key before/after 值1 值2

性能总结:

他是一个字符串链表,left,right都可以插入添加

  • 如果键不存在,创建新的链表
  • 如果键已经存在,新增内容
  • 值全部移除,key消失
  • 由于是链表,所以它对头和尾操作的效率都极高,但是假如是对中间元素的操作,效率就可怜了

Set:等同于java中的Map<String,Set<String>>

  • 第一眼看到set,有没有想起来,它不允许有重复的元素? 没错,它的底层是有hashTable实现的,天生去重

Set的所有指令,全部以 s 开头

常用命令 命令
添加值 sadd key values
查看值 smembers key
检查集合是否有值 sismember key value
查看set集合里面的元素个数 scard key
删除集合中的指定元素 srem key value
随机弹出某个元素 srandmember key
随机出栈 spop key
把key1中的某个值赋值给key2 smove SourceKey destKey member
添加值 sadd key values
查看值 smembers key
添加值 sadd key values
查看值 smembers key
数学集合类 命令
差集 sdiff
交集 sinte
并集 sunion

Zset(sorted set: 有序集合)sort_set:可排序的set

  • 首先: 它同样具有set的特性,去重!
  • 其次: 每一个元素的value之前会关联上一个double类型的分数.redis会按照分数的成员,从小到大进行排序.(分数可以重复) 据说,我们平时玩的游戏得分排行榜就是它搞的

set的值是 k1 v1 k2 v2
zset的值 K1 score v1 k2 score v2


补充常用命令

点击查看所有命令

数据库的相关命令 指令
关闭redis shutdown
选择数据库 select 库索引
查看当前数据库中key的数量 Dbsize
清空当前库 Flushdb
通杀所有库 Flushall
key常用命令 指令
查看所有key keys *
判断某个key是否存在 exists key
把key移动到别的库 move key db
为key 设定过期时间 expire key 秒钟
查看还有多少秒过期 ttl key
查看当前key是什么类型的 type key

RDB & AOF

Redis有两种方式支持持久化,RDB(redis database)与AOF(append only file)

RDB是什么?

就是在指定的时间把把内存中的数据快照(snapshot)写入磁盘, 恢复数据是将快照文件从磁盘读取到内存

redis是单线程的,他是怎么分神持久化的呢?

会单独(创建)fork一个子进程,负责持久化,子进程把数据写进一个临时文件,等这个持久化的过程完成之后,用这个临时文件替换原来的rdb文件,整个过程中,主进程不会进行任何IO操作,这也就极大的提高了redis的可用性,尤其是对大规模的文件的恢复,RDB的优势远远高于AOF , 当然她也有缺点,加入突然断电了,redis没来的及fork,就会丢失最后一份文件

redis.config中有关RDB的配置如下:为了容易区分我写的笔记,会从中间断开,但是其实他们还是完整的一段

################################ SNAPSHOTTING  ################################
#
# Save the DB on disk:
#
#   save <seconds> <changes>
#
#   Will save the DB if both the given number of seconds and the given
#   number of write operations against the DB occurred.
#
#   In the example below the behaviour will be to save:
#   after 900 sec (15 min) if at least 1 key changed
#   after 300 sec (5 min) if at least 10 keys changed
#   after 60 sec if at least 10000 keys changed
#
#   Note: you can disable saving completely by commenting out all "save" lines.
#
#   It is also possible to remove all the previously configured save
#   points by adding a save directive with a single empty string argument
#   like in the following example:
#

把下面的注释打开就会禁用掉RDB的持久化策略

#   save ""

RDB是整个内存压缩过的Snapshot,RDB的数据结构,可以配置复合的快照触发条件,如下

save 900 1          #15分钟内key改变了1次
save 300 10         #五分钟内改变了十次
save 60 10000       #一分钟内改变了一万次


# By default Redis will stop accepting writes if RDB snapshots are enabled
# (at least one save point) and the latest background save failed.
# This will make the user aware (in a hard way) that data is not persisting
# on disk properly, otherwise chances are that no one will notice and some
# disaster will happen.
#
# If the background saving process will start working again Redis will
# automatically allow writes again.
#
# However if you have setup your proper monitoring of the Redis server
# and persistence, you may want to disable this feature so that Redis will
# continue to work as usual even if there are problems with disk,
# permissions, and so forth.
stop-writes-on-bgsave-error yes

# Compress string objects using LZF when dump .rdb databases?
# For default that's set to 'yes' as it's almost always a win.
# If you want to save some CPU in the saving child set it to 'no' but
# the dataset will likely be bigger if you have compressible values or keys.

对于储存到磁盘中的快照,我们可以设置是否进行压缩储存,如果是的化,redis会采用LZF压缩算法进行压缩,如果你不想消耗CPU进行压缩,可以把它关闭

rdbcompression yes

# Since version 5 of RDB a CRC64 checksum is placed at the end of the file.
# This makes the format more resistant to corruption but there is a performance
# hit to pay (around 10%) when saving and loading RDB files, so you can disable it
# for maximum performances.
#
# RDB files created with checksum disabled have a checksum of zero that will
# tell the loading code to skip the check.

在存储快照后,还可以让redis使用CRC64算法进行数据校验,但是这样会增加大约 10%的性能消耗

rdbchecksum yes

# The filename where to dump the DB

默认的文件名

dbfilename dump.rdb
# The working directory.
#
# The DB will be written inside this directory, with the filename specified
# above using the 'dbfilename' configuration directive.
#
# The Append Only File will also be created inside this directory.
#
# Note that you must specify a directory here, not a file name.
dir ./

######################################################################################

其他方法触发RDB快照?

  • save命令: 只管保存,但是会堵塞其他的操作(一般这个命令都是在夜深人静的时候偷偷做)
  • bgsave: 异步进行快照操作,同时还可以响应客户端的请求, 通过lastsave命令获取最后一次执行的时间
  • 执行flushall命令,清空所有, 同样会产生dump.rdb ,但是他是空的,没有任何意义

如何恢复?

  • 一般想恢复数据,会进行冷拷贝,就是说,这台挂了的redis的dump.rdb文件其实在别的机器上有实时的备份, 所以我们把备份的dump.rdb移动到redis的安装目录然后启动(通过 config get dir 获取本目录)

优势

  • 对于大规模,且数据的完整性一致性要求不高的数据的恢复,它表现的很突出!

劣势

  • 他每隔一段时间才会备份,假如说真的停电了,那么最后一份数据没有备份,肯定就丢失了!
  • 每次备份时的fork操作,就算我们不考虑子进程会影响主进程的资源,那么内存中的数据突然膨胀为两倍也是需要考虑的

AOF是什么?

AOF是redis第二种持久化策略,它以日志的形式实时记录每个写操作,而且,他的规则是只追加,不修改! redis重启后会读取该文件,挨个执行里面的命令,完成数据恢复

如何开启AOF,及AOF的配置策略 ?

下面的配置问价截取自 redis.config关于aof部分

############################## APPEND ONLY MODE ###############################

# By default Redis asynchronously dumps the dataset on disk. This mode is
# good enough in many applications, but an issue with the Redis process or
# a power outage may result into a few minutes of writes lost (depending on
# the configured save points).
#
# The Append Only File is an alternative persistence mode that provides
# much better durability. For instance using the default data fsync policy
# (see later in the config file) Redis can lose just one second of writes in a
# dramatic event like a server power outage, or a single write if something
# wrong with the Redis process itself happens, but the operating system is
# still running correctly.
#
# AOF and RDB persistence can be enabled at the same time without problems.
# If the AOF is enabled on startup Redis will load the AOF, that is the file
# with the better durability guarantees.
#
# Please check http://redis.io/topics/persistence for more information.

开启AOF, 修改下面的只追加为 yes

appendonly yes

# The name of the append only file (default: "appendonly.aof")

默认的名字

appendfilename "appendonly.aof"

下面一段的大意是,redis通过fsync()调用告诉操作系统实际在磁盘上写入数据,而不是在输出缓冲区中等待更多的数据,具体有下面的三种策略 always everysec no

# The fsync() call tells the Operating System to actually write data on disk
# instead of waiting for more data in the output buffer. Some OS will really flush
# data on disk, some other OS will just try to do it ASAP.
#
# Redis supports three different modes:
#
# no: don't fsync, just let the OS flush the data when it wants. Faster.
# always: fsync after every write to the append only log. Slow, Safest.
# everysec: fsync only one time every second. Compromise.
#
# The default is "everysec", as that's usually the right compromise between
# speed and data safety. It's up to you to understand if you can relax this to
# "no" that will let the operating system flush the output buffer when
# it wants, for better performances (but if you can live with the idea of
# some data loss consider the default persistence mode that's snapshotting),
# or on the contrary, use "always" that's very slow but a bit safer than
# everysec.
#
# More details please check the following article:
# http://antirez.com/post/redis-persistence-demystified.html
#
# If unsure, use "everysec".

这是那具体的三条配置

  • always : 同步持久化,每次发生数据变更,立刻记录到磁盘,性能比较差,但是数据完整性很好
  • everysec: 出场的默认推荐,异步记录,每秒钟记录一次,如果宕机,丢失一秒数据
  • no: 不记录
# appendfsync always
appendfsync everysec
# appendfsync no

# When the AOF fsync policy is set to always or everysec, and a background
# saving process (a background save or AOF log background rewriting) is
# performing a lot of I/O against the disk, in some Linux configurations
# Redis may block too long on the fsync() call. Note that there is no fix for
# this currently, as even performing fsync in a different thread will block
# our synchronous write(2) call.
#
# In order to mitigate this problem it's possible to use the following option
# that will prevent fsync() from being called in the main process while a
# BGSAVE or BGREWRITEAOF is in progress.
#
# This means that while another child is saving, the durability of Redis is
# the same as "appendfsync none". In practical terms, this means that it is
# possible to lose up to 30 seconds of log in the worst scenario (with the
# default Linux settings).

# If you have latency problems turn this to "yes". Otherwise leave it as
# "no" that is the safest pick from the point of view of durability.

重启的时候是否可以运行Appendfsync,使用默认的no就行,保证数据安全性

no-appendfsync-on-rewrite no

# Automatic rewrite of the append only file.
# Redis is able to automatically rewrite the log file implicitly calling
# BGREWRITEAOF when the AOF log size grows by the specified percentage.
#
# This is how it works: Redis remembers the size of the AOF file after the
# latest rewrite (if no rewrite has happened since the restart, the size of
# the AOF at startup is used).
#
# This base size is compared to the current size. If the current size is
# bigger than the specified percentage, the rewrite is triggered. Also
# you need to specify a minimal size for the AOF file to be rewritten, this
# is useful to avoid rewriting the AOF file even if the percentage increase
# is reached but it is still pretty small.
#
# Specify a percentage of zero in order to disable the automatic AOF
# rewrite feature.

设置重写的基础值 (在这里说一下,啥是重写? 随着redis工作时间的增加,appendonly.aof文件的体积越来越大!!!,为了给节省空间,重写aof文件, 去掉所有没用的命令,达到瘦身的效果)

auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb  # 一般企业3G起步

# An AOF file may be found to be truncated at the end during the Redis
# startup process, when the AOF data gets loaded back into memory.
# This may happen when the system where Redis is running
# crashes, especially when an ext4 filesystem is mounted without the
# data=ordered option (however this can't happen when Redis itself
# crashes or aborts but the operating system still works correctly).
#
# Redis can either exit with an error when this happens, or load as much
# data as possible (the default now) and start if the AOF file is found
# to be truncated at the end. The following option controls this behavior.
#
# If aof-load-truncated is set to yes, a truncated AOF file is loaded and
# the Redis server starts emitting a log to inform the user of the event.
# Otherwise if the option is set to no, the server aborts with an error
# and refuses to start. When the option is set to no, the user requires
# to fix the AOF file using the "redis-check-aof" utility before to restart
# the server.
#
# Note that if the AOF file will be found to be corrupted in the middle
# the server will still exit with an error. This option only applies when
# Redis will try to read more data from the AOF file but not enough bytes
# will be found.
aof-load-truncated yes

# When rewriting the AOF file, Redis is able to use an RDB preamble in the
# AOF file for faster rewrites and recoveries. When this option is turned
# on the rewritten AOF file is composed of two different stanzas:
#
#   [RDB file][AOF tail]
#
# When loading Redis recognizes that the AOF file starts with the "REDIS"
# string and loads the prefixed RDB file, and continues loading the AOF
# tail.
#
# This is currently turned off by default in order to avoid the surprise
# of a format change, but will at some point be used as the default.
aof-use-rdb-preamble no
######################################################################################

开启后,重启redis,会创建出appendonly.aof文件,里面记录的就是我们所有的写操作

实操场景

  1. 假如说我们是执行flushall命令,清空了redis, appendonly.aof同样会记录下这条命令,所以,我们想恢复数据的话,需要去除appendonly.aof里面的flushall命令

  2. 假如说,redis使用AOF记录着我们的写操作,这时候突然断电了... appendonly.aof文件里面记录上了一条不完整的命令, 好,来电开机,!!! 我们是开不了机的,会报错! 这说明下面这个问题

    • aof 和 rdb共存,优先查找的是aof
      如何修复呢appendonly.aof文件?

在redis的安装目录下面有两个脚本文件 , 分别修复aof和rdb文件

命令

redis-check-aof  --fix appendonly.aof

图片

关于AOF的rewirte

  • rewirte是什么?

AOF采取的是文件追加的方式,文件的体积越来越大,为了优化这种现象,增加了重写机制,当aof文件的体积到达我们在上面的配置文件上的阕值时,就会触发重写策略,只保留和数据恢复相关的命令

  • 手动重写
bgrewriteaof
  • 重写的原理?

配置文件的阕值达到时,redis会fork出一条新的进程,(同样是先复制到一份新的临时文件,最后再rename),遍历每一条语句,记录下有set的语句

  • 触发机制?

redis会记录下,上次重写时aof的大小,默认配置是,当aof文件的大小是上次重写后aof文件大小的一倍且文件大于64M时,触发

优势

它既可以每秒同步,也可以实时同步,也可以不同步,数据完整性更强

劣势

aof文件的体积远远大于rdb文件,恢复的速度也会比rdb文件缓慢

总结一下:AOF是一个只追加的日志文件,用于数据恢复,当它的体积到达一定大时,redis会rewrite它,

AOF 与 RDB 的抉择

  • 两者的优缺点,上面已经论述过,这里不再唠叨
  • 如果我们的redis只是简单的作为缓存,那两者都不要也没事
  • 同时开启两者: 在这种情况下,redis优先加载的是aof,因为它的数据很可能比rdb更全,但是并不建议只是用aof,因为aof不是那么的安全,很可能存在潜在的bug

关于性能的建议:

  • 因为RDB只是用于后备用途,因此建议在从机slave上只备份rdb文件,而且只要15分钟备份一次就够了
  • 如果启动了aof,我们尽量减少rewrite的频率,基础大小设置为5G完全可以,起步也要3G
  • 如果我们不选择aof, 而是选择了主从复制的架构实现高可用同样可以,能省掉一大笔IO操作,但是意外发生的话,会丢失十几分钟的数据,新浪选择的就是这种架构

事务

什么是事务?

事务可以理解成一组写命令的集合,一组事务中的所有命令都会序列化,这组命令会按顺序串行执行,一次性,顺序性,排他性的执行一系列命令,不允许加塞

redis中的事务命令 命令
开启事务 MULTI
监控key,如果在事务执行之前key被其他命令改动,事务被打断 WATCH key1 key2 ...
取消监控 UNWATCH
取消事务 DISCARD
提交事务 EXEC
  • 开启事务后经常会遇到下面两种情况
    • 这组将要持久化的命令中某一条,出现了语法错误,提交事务,整组命令会连做,全部取消
    • 这组将要持久化的命令中某一条,出现了逻辑错误,比如给字母a加1,提交事务,单条语句取消,其它不变

通过上面两点对比,我们可以发现,其实redis对事务的支持其实是片面的

监控锁机制watch

如何使用?

在开启事务之前,声明一下要监控的键watch key1 key2 ..., 它相当于一把乐观锁,当我们行锁,会记录数据的版本号,提交事务时,如果发现版本号改变了,那么回滚,取消本次操作

redis事务的三大特性

  • 单独的隔离操作: 事务中的所有命令都会被序列化,按顺序执行,也不会被其他客户端发来的请求打断
  • 没有隔离级别的概念: 这组事务在提交之前不会被真正的执行,因此存在着这样的情况,事务内的查询看不到实事务里的更新,他只是提示我们queued(命令入队),事务外的查询也查询不到事务内的更新
  • 不能保证原子性: 就算是有一条命令执行失败了,其他命令依然会执行,没有回滚

相对于传统的事务的特性:

  • A(Atomicity)
  • C(Consistency)
  • I(Isolation)
  • D(Durability)

nosql同样也有一套属于自己的CAP

  • C(Consistency 强一致性)
  • A(Availability可用性)
  • P(Partition tolerance分区容错性)

CAP 的理论核心是: 一个分布式的系统,不可能很好的满足一致性,可用性,分区容错性这三个需求,最多同时只能满足两个.因此CAP原理将nosql分成了三大原则:

  • CA- 单点集群,满足强一致性和可用性,比如说oracle,扩展性收到了限制
  • CP- 满足一致性,和分区容错性Redis和MongoDB都属于这种类型
  • AP- 选择了可用性和分区容错性,他也是大多数网站的选择,容忍数据可以暂时不一致,但是不容忍系统挂掉

由于硬件或者网络在传输数据的时候出现丢包的现象, Partition tolerrance是我们必选的, 因此只能在强一致性和可用性之间进行权衡,没有任何nosql可以同时满足上面的三点,redis选择了强一致性, 至于可用性怎么整? 我们可以搭建集群,做备份,尤其是第七部分的主流的主从复制读写分离可以很有效的解决这个问题

主从复制,读写分离

什么是主从复制,读写分离?

据说这是一句行话,意思就是说,主机的数据更新后会根据配置和策略,自动的同步到备机的master和slaver机制,说白了,就是redis坚决不能挂, 主机挂了,从机顶上,从机挂了,挂了就挂了吧,反正主机还在

怎么玩?

  • 2.1 配置从库,让他认祖归宗
slaveof 主机ip 主机端口

从机每次和主机断开后,重启都要重新连接,除非我们把更改配置文件,让他自动认祖归宗

  • 2.2如何搭建起master-slaver集群

说白了,就是启动多个redis,如果我们是在单机Linux模仿,就得做如下几件事,比如改端口,总不能都用6379吧

  1. 拷贝多份配置文件, redis.conf
  2. 全部开启daemonize yes # 允许redis后台运行
  3. 修改pid文件的名字
  4. 修改端口
  5. 修改log的名字
  6. 修改Dump.rdb名字 # 上面说了,slave从机仅仅备份的是主机的dump.rdb文件

常见的三种模式

1.一主二仆

  • 我们需要手动给slave设置它的依附的主机slaveof 主机ip 端口

主机新添加后,从机会立即备份

  • 查看一主二仆的状态
info replication
  • 一主二仆的主人仆人挨个挂的几种情况
    • 主机挂---默认从机原地待命
    • 主机复活--- 从机认主归宗
    • 从机挂 --- 从机复活后,不再认识老主人,翻身成主机,我们需要再次手动执行命令,让他认祖归宗
  1. 星火相传

上一个slave 逻辑上可以是下一个slave的Master,Slave同样可以就收其他slave的连接和同步的请求,成一条链

命令

slaceof 新ip 新端口
  1. 反客为主

反客为主,有两种模式,自动版和手动版

手动版:

  1. 主机挂
  2. 从机默认等待
  3. 我们选一台从机当作新主机,手动敲命令slaveof no one
  4. 让其他从机认新主机为主 挨个敲slaveof 新主机ip 端口--组成新体系
  5. 老主机复活,和新体系没一毛钱关系

自动版:--- 哨兵模式

他可以自动监控主机是否有故障,如果主机有故障,它会根据投票数选取一个从库担任新的主机,老主机复活,被哨兵抓到,成为新主机的从机

怎么玩?

  • 新建sentinel.conf文件
  • 配置
sentinel monitor host6379 127.0.0.1 6379 1

6379host是被监控的主机名字(自定义) , 最后的1表示主机挂掉后,让salve投票选举新主机

  • 启动哨兵(可以同时监控多个master)

图片

执行上图的 redis-sentinel + 我们上面新建的sentinel.conf文件路径

复制的缺点: 所有的写操作都是现在master上操作,再同步到slave上,难免会产生延迟,尤其是系统繁忙或者网络拥堵,slave的数量的增加,这种现象更严重

原文地址:https://www.cnblogs.com/ZhuChangwu/p/11150535.html