Sentinel是一个管理多个redis实例的工具,它可以实现对redis的监控、通知、自动故障转移。sentinel不断的检测redis实例是否可以正常工作,通过API向其他程序报告redis的状态,如果redis master不能工作,则会自动启动故障转移进程,将其中的一个slave提升为master,其他的slave重新设置新的master实例。也就是说,它提供了:
监控(Monitoring): Sentinel 会不断地检查你的主实例和从实例是否正常。
通知(Notification): 当被监控的某个 Redis 实例出现问题时, Sentinel 进程可以通过 API 向管理员或者其他应用程序发送通知。
自动故障迁移(Automatic failover): 当一个主redis实例失效时, Sentinel 会开始记性一次failover, 它会将失效主实例的其中一个从实例升级为新的主实例, 并让失效主实例的其他从实例改为复制新的主实例; 而当客户端试图连接失效的主实例时, 集群也会向客户端返回新主实例的地址, 使得集群可以使用新主实例代替失效实例。
Redis Sentinel自身也是一个分布式系统, 你可以在一个架构中运行多个 Sentinel 进程, 这些进程使用流言协议(gossip protocols)来接收关于主Redis实例是否失效的信息, 然后使用投票协议来决定是否执行自动failover,以及评选出从Redis实例作为新的主Redis实例。
1.启动sentinel的方法
当前Redis stable版已经自带了redis-sentinel这个工具。虽然 Redis Sentinel 已经提供了一个单独的可执行文件 redis-sentinel , 但实际上它只是一个运行在特殊模式下的 Redis实例, 你可以在启动一个普通 Redis实例时通过给定 –sentinel 选项来启动 Redis Sentinel 实例。也就是说:
redis-sentinel /path/to/sentinel.conf
等同于
redis-server /path/to/sentinel.conf --sentinel
其中sentinel.conf是redis的配置文件,Redis sentinel会需要写入配置文件来保存sentinel的当前状态。当配置文件无法写入时,Sentinel启动失败。
2. sentinel的配置
一个简单的sentinel配置文件实例如下:
1
2
3
4
5
6
port 26329
sentinel monitor myredis 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 60000
sentinel failover-timeout mymaster 180000
sentinel parallel-syncs mymaster 1
sentinel notification-script myredis <script-path>
sentinel 选项的名字 主Redis实例的名字 选项的值
配置文件的格式为:
第一行配置指示 Sentinel 去监视一个名为 mymaster 的主redis实例, 这个主实例的 IP 地址为本机地址127.0.0.1 , 端口号为 6379 , 而将这个主实例判断为失效至少需要 2 个 Sentinel 进程的同意,只要同意 Sentinel 的数量不达标,自动failover就不会执行。同时,一个Sentinel都需要获得系统中大多数Sentinel进程的支持, 才能发起一次自动failover, 并预留一个新主实例配置的编号。而当超过半数Redis不能正常工作时,自动故障转移是无效的。
各个选项的功能如下:
down-after-milliseconds 选项指定了 Sentinel 认为Redis实例已经失效所需的毫秒数。
当实例超过该时间没有返回PING,或者直接返回错误, 那么 Sentinel 将这个实例标记为主观下线(subjectively down,简称 SDOWN )。只有一个 Sentinel进程将实例标记为主观下线并不一定会引起实例的自动故障迁移: 只有在足够数量的 Sentinel 都将一个实例标记为主观下线之后,实例才会被标记为客观下线(objectively down, 简称 ODOWN ), 这时自动故障迁移才会执行。具体的行为如下:
(1). 每个 Sentinel 每秒一次向它所监控的主实例、从实例以及其他 Sentinel 实例发送一个 PING 命令。当一个实例(instance)距离最后一次有效回复 PING 命令的时间超过 down-after-milliseconds 选项所指定的值, 那么这个实例会被 Sentinel 标记为主观下线。如果一个主实例被标记为主观下线, 并且有足够数量的 Sentinel (至少要达到配置文件指定的数量)在指定的时间范围内同意这一判断, 那么这个主实例被标记为客观下线。
(2).在一般情况下, 每个 Sentinel 进程会以每 10 秒一次的频率向它已知的所有主实例和从实例发送 INFO 命令。 当一个主实例被 Sentinel实例标记为客观下线时, Sentinel 向下线主实例的所有从实例发送 INFO 命令的频率会从 10 秒一次改为每秒一次。
(3).当没有足够数量的 Sentinel 同意主实例已经下线, 主Redis服务实例的客观下线状态就会被移除。 当主服务器重新向 Sentinel 的PING 命令返回有效回复时, 主服务器的主观下线状态就会被移除。
parallel-syncs 选项指定了在执行故障转移时, 最多可以有多少个从Redis实例在同步新的主实例, 在从Redis实例较多的情况下这个数字越小,同步的时间越长,完成故障转移所需的时间就越长。
尽管复制过程的绝大部分步骤都不会阻塞从实例, 但从redis实例在载入主实例发来的 RDB 文件时, 仍然会造成从实例在一段时间内不能处理命令请求: 如果全部从实例一起对新的主实例进行同步, 那么就可能会造成所有从Redis实例在短时间内全部不可用的情况出现。
所以从实例被设置为允许使用过期数据集(参见对 redis.conf 文件中对 slave-serve-stale-data 选项),可以缓解所有从实例都在同一时间向新的主实例发送同步请求的负担。你可以通过将这个值设为 1 来保证每次只有一个从Redis实例处于不能处理命令请求的同步状态。
failover-timeout如果在该时间(ms)内未能完成failover操作,则认为该failover失败。
notification-script: 指定sentinel检测到该监控的redis实例指向的实例异常时,调用的报警脚本。该配置项可选,但是很常用。
3. Sentinel集群的运行机制
一个 Sentinel进程可以与其他多个 Sentinel进程进行连接, 每个 Sentinel进程之间可以互相检查对方的可用性, 并进行信息交换。
和其他集群不同的是,你无须设置其他Sentinel的地址,Sentinel进程可以通过发布与订阅来自动发现正在监视相同主实例的其他Sentinel。同样,你也不必手动列出主实例属下的所有从实例,因为Sentinel实例可以通过询问主实例来获得所有从实例的信息。
每个 Sentinel 都订阅了被它监视的所有主服务器和从服务器的 __sentinel__:hello 频道, 查找之前未出现过的 sentinel进程。 当一个 Sentinel 发现一个新的 Sentinel 时,它会将新的 Sentinel 添加到一个列表中,这个列表保存了 Sentinel 已知的,监视同一个主服务器的所有其他Sentinel。
4. 启动Redis和sentinel
下面的测试环境为ubuntu 14.04 LTS,Redis 2.8.19。下面首先配置一个小型的M/2S环境。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
/etc/redis/redis-m.conf
daemonize yes
pidfile /var/run/redis/redis-server-m.pid
port 6379
loglevel notice
logfile /var/log/redis/redis-server-m.log
databases 16
##disable snapshot
save ""
dir /app/redis-m
appendonly yes
appendfilename "appendonly.aof"
##not to be a slave
#slaveof no one

/etc/redis/redis-s1.conf
daemonize yes
pidfile /var/run/redis/redis-server-s1.pid
port 6380
loglevel warning
logfile /var/log/redis/redis-server-s1.log
databases 16
##disable snapshot
save ""
dir /app/redis-s1
appendonly yes
appendfilename "appendonly.aof"
##to be a slave

/etc/redis/redis-s2.conf
daemonize yes
pidfile /var/run/redis/redis-server-s2.pid
port 6381
loglevel warning
logfile /var/log/redis/redis-server-s2.log
databases 16
##disable snapshot,enable AOF
save ""
dir /app/redis-s2
appendonly yes
appendfilename "appendonly.aof"
##to be a slave
slaveof 127.0.0.1 6379
启动后,查看进程和复制状态是否正常:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
ps -ef | grep redis
root 17560 1 0 09:48 ? 00:00:00 redis-server *:6379
root 17572 1 0 09:48 ? 00:00:00 redis-server *:6380
root 17609 1 0 09:49 ? 00:00:00 redis-server *:6381

redis-cli
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=127.0.0.1,port=6380,state=online,offset=547,lag=0
slave1:ip=127.0.0.1,port=6381,state=online,offset=547,lag=1
master_repl_offset:547
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:546
前面我们了解了,Sentinel可以通过master Redis实例来获得它的从实例的信息。所以每一个Sentinel只配置主实例的监控即可。Sentinel之间端口有所不同。
1
2
3
4
5
6
port 26379
sentinel monitor myredis 127.0.0.1 6379 2
sentinel down-after-milliseconds myredis 60000
sentinel failover-timeout myredis 180000
sentinel parallel-syncs myredis 1
sentinel notification-script myredis /etc/redis/log-issues.sh
其中,通知脚本简单的记录一下failover事件。
1
2
3
#!/bin/bash

echo "master failovered at `date`" > /root/redis_issues.log
另外两个端口分别为port 26380。然后通过redis-sentinel命令来启动两个sentinel实例。
1
2
3
4
# nohup redis-sentinel /etc/redis/sentinel1.conf > /root/sentinel1.log 2>&1 &
[1] 18207
# nohup redis-sentinel /etc/redis/sentinel2.conf > /root/sentinel2.log 2>&1 &
[2] 18212
通过日志输出可以看出已经成功监控master和两个slave。并和另一个sentinel进程通信。
1
2
3
4
5
[18207] 08 May 13:28:29.336 # Sentinel runid is d72be991001b994568d3de1b746f611884b0343a
[18207] 08 May 13:28:29.336 # +monitor master myredis 127.0.0.1 6379 quorum 2
[18207] 08 May 13:28:29.339 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ myredis 127.0.0.1 6379
[18207] 08 May 13:28:29.339 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ myredis 127.0.0.1 6379
[18207] 08 May 13:28:36.602 * +sentinel sentinel 127.0.0.1:26479 127.0.0.1 26479 @ myredis 127.0.0.1 6379
5. 连接Sentinel和主动failover
在默认情况下,Sentinel 使用TCP端口26379(普通 Redis 服务器使用的是 6379)。Sentinel 接受 Redis 协议格式的命令请求, 所以你可以使用 redis-cli 或者任何其他 Redis 客户端来与 Sentinel 进行通讯。
有两种方式可以和 Sentinel 进行通讯:
第一种方法是通过直接发送命令来查询被监视 Redis 服务器的当前状态, 以及进行主动转移等操作。这些命令包括:
(1). PING :返回 PONG 。
1
2
3
# redis-cli -p 26379
127.0.0.1:26379> ping
PONG
(2). SENTINEL masters :列出所有被监视的主Redis服务实例,以及这些主服务实例的当前状态。SENTINEL slaves :列出给定主服务实例的所有从实例,以及这些从实例的当前状态。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
127.0.0.1:26379> sentinel masters
1) 1) "name"
2) "myredis"
3) "ip"
4) "127.0.0.1"
5) "port"
6) "6379"
7) "runid"
8) "a88ffd6548e333f3ac895cf1b890ef32a527dd66"
......
37) "parallel-syncs"
38) "1"
39) "notification-script"
40) "/etc/redis/log-issues.sh"
127.0.0.1:26379> sentinel slaves myredis
1) 1) "name"
2) "127.0.0.1:6381"
3) "ip"
4) "127.0.0.1"
5) "port"
6) "6381"
......
2) 1) "name"
2) "127.0.0.1:6380"
3) "ip"
4) "127.0.0.1"
5) "port"
6) "6380"
.......
(3). SENTINEL get-master-addr-by-name : 返回给定名字的主实例的 IP 地址和端口号。 如果这个主实例正在执行故障转移操作, 或者针对这个主实例的故障转移操作已经完成, 那么这个命令返回新的主服务器的 IP 地址和端口号。
1
2
3
127.0.0.1:26379> sentinel get-master-addr-by-name myredis
1) "127.0.0.1"
2) "6379"
(4). SENTINEL reset : 重置所有名字和给定模式 pattern 相匹配的主服务器。 pattern 参数是一个 Glob 风格的模式。 重置操作清除该sentinel的所保存的所有状态信息,并进行一次重新的发现过程。
127.0.0.1:26379> sentinel reset myredis
(integer) 1
(5). SENTINEL failover :进行一次主动的failover。即在不询问其他 Sentinel 意见的情况下, 强制开始一次自动故障迁移 。发起故障转移的 Sentinel 会向其他 Sentinel 发送一个新的配置,其他 Sentinel 会根据这个配置进行相应的更新。
1
2
127.0.0.1:26379> sentinel failover myredis
OK
## master切换到了localhost:6381上。
1
2
3
4
5
6
7
8
9
10
11
127.0.0.1:26379> sentinel get-master-addr-by-name myredis
1) "127.0.0.1"
2) "6381"
## redis-cli中
redis-cli
127.0.0.1:6379> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6381
master_link_status:up
第二种方法是使用发布与订阅功能, 通过接收 Sentinel 发送的通知: 当执行故障转移操作, 或者某个被监视的实例被判断为主观下线或者客观下线时, Sentinel 就会发送相应的信息。
一个频道能够接收和这个频道的名字相同的事件。 比如说, 名为 +sdown 的频道就可以接收所有实例进入主观下线(SDOWN)状态的事件。
通过执行 PSUBSCRIBE * 命令可以接收所有事件信息。例如:
1
2
3
4
5
127.0.0.1:26379> PSUBSCRIBE *
Reading messages... (press Ctrl-C to quit)
1) "psubscribe"
2) "*"
3) (integer) 1
###此时进行一次主动的failover,各个频道的输出中涉及了新纪元(epoch)通知、投票、选举、新主和新slave的通告、角色转变通知,最终完成了这次主动failover过程。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
1) "pmessage"
2) "*"
3) "+new-epoch"
4) "2"
1) "pmessage"
2) "*"
3) "+try-failover"
4) "master myredis 127.0.0.1 6381"
1) "pmessage"
2) "*"
3) "+vote-for-leader"
4) "d72be991001b994568d3de1b746f611884b0343a 2"
1) "pmessage"
2) "*"
3) "+elected-leader"
4) "master myredis 127.0.0.1 6381"
1) "pmessage"
2) "*"
3) "+failover-state-select-slave"
4) "master myredis 127.0.0.1 6381"
1) "pmessage"
2) "*"
3) "+selected-slave"
4) "slave 127.0.0.1:6380 127.0.0.1 6380 @ myredis 127.0.0.1 6381"
1) "pmessage"
2) "*"
3) "+failover-state-send-slaveof-noone"
4) "slave 127.0.0.1:6380 127.0.0.1 6380 @ myredis 127.0.0.1 6381"
1) "pmessage"
2) "*"
3) "+failover-state-wait-promotion"
4) "slave 127.0.0.1:6380 127.0.0.1 6380 @ myredis 127.0.0.1 6381"
1) "pmessage"
2) "*"
3) "-role-change"
4) "slave 127.0.0.1:6380 127.0.0.1 6380 @ myredis 127.0.0.1 6381 new reported role is master"
1) "pmessage"
2) "*"
3) "+promoted-slave"
4) "slave 127.0.0.1:6380 127.0.0.1 6380 @ myredis 127.0.0.1 6381"
1) "pmessage"
2) "*"
3) "+failover-state-reconf-slaves"
4) "master myredis 127.0.0.1 6381"
1) "pmessage"
2) "*"
3) "+slave-reconf-sent"
4) "slave 127.0.0.1:6379 127.0.0.1 6379 @ myredis 127.0.0.1 6381"
1) "pmessage"
2) "*"
3) "+slave-reconf-inprog"
4) "slave 127.0.0.1:6379 127.0.0.1 6379 @ myredis 127.0.0.1 6381"
1) "pmessage"
2) "*"
3) "+slave-reconf-done"
4) "slave 127.0.0.1:6379 127.0.0.1 6379 @ myredis 127.0.0.1 6381"
1) "pmessage"
2) "*"
3) "+failover-end"
4) "master myredis 127.0.0.1 6381"
1) "pmessage"
2) "*"
3) "+switch-master"
4) "myredis 127.0.0.1 6381 127.0.0.1 6380"
1) "pmessage"
2) "*"
3) "+slave"
4) "slave 127.0.0.1:6379 127.0.0.1 6379 @ myredis 127.0.0.1 6380"
1) "pmessage"
2) "*"
3) "+slave"
4) "slave 127.0.0.1:6381 127.0.0.1 6381 @ myredis 127.0.0.1 6380"
1) "pmessage"
2) "*"
3) "-role-change"
4) "slave 127.0.0.1:6381 127.0.0.1 6381 @ myredis 127.0.0.1 6380 new reported role is master"
1) "pmessage"
2) "*"
3) "+role-change"
4) "slave 127.0.0.1:6381 127.0.0.1 6381 @ myredis 127.0.0.1 6380 new reported role is slave"
由此可见,一次failover的过程如下:
一次故障转移操作由以下步骤组成:
(1). 由sentinel主动发起failover或者发现主服务器已经进入客观下线状态。
(2). sentinel对我们的当前纪元(epoch)进行自增,并尝试在这个纪元中当选为此次failover的总指挥。
(3). 如果当选失败, 那么在设定的故障迁移超时时间的两倍之后, 重新尝试当选。 如果当选成功, 那么执行以下步骤。
(4). 选出一个从redis实例,并将它升级为主redis实例。
(5). 向被选中的从redis实例发送 SLAVEOF NO ONE 命令,让它转变为主redis实例。
(6). 通过发布与订阅功能, 将更新后的配置传播给所有其他 Sentinel , 其他 Sentinel 对它们自己的配置进行更新。
(7). 向已下线主服务器的从服务器发送SLAVEOF命令, 让它们去复制新的主服务器。
(8). 当所有从redis实例都已经开始复制新的主redis实例时, 领头Sentinel 终止这次故障迁移操作。
6. 被动failover场景测试
当前状态,主failover为6380
1
2
3
4
5
127.0.0.1:6379> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6380
关闭6380Redis实例,等待down-after-milliseconds后,sentinel的日志有如下输出,证明切换成功。
1
2
3
4
5
6
7
[18207] 08 May 14:20:32.784 # +sdown master myredis 127.0.0.1 6380
[18207] 08 May 14:20:32.855 # +odown master myredis 127.0.0.1 6380 #quorum 2/2
[18207] 08 May 14:20:32.855 # +new-epoch 3
......投票、选举......
[18207] 08 May 14:20:34.989 # +switch-master myredis 127.0.0.1 6380 127.0.0.1 6381
[18207] 08 May 14:20:34.989 * +slave slave 127.0.0.1:6379 127.0.0.1 6379 @ myredis 127.0.0.1 6381
[18207] 08 May 14:20:34.992 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ myredis 127.0.0.1 6381
启动6380实例,它会自己作为slave连接行6381这个master节点上。
1
2
3
4
5
6
7
8
$ redis-server /etc/redis/redis-s1.conf
$ redis-cli -p 6380
127.0.0.1:6380> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6381
master_link_status:up
测试成功。最后需要注意的是,sentinel集群自身也需要多数机制,也就是2个sentinel进程时,挂掉一个另一个就不可用了。
7. Sentinel的客户端
如果要做到应用程序(客户端)对Redis的failover透明Transparent),客户端需要监控sentinel的频道信息,并自动连接新的主节点。官方提供了一个专门的topic来讲解这个问题:Guidelines for Redis clients with support for Redis Sentinel,而一些常用的开发语言也已经有了整合sentinel的redis driver:
Python redis 2.10.3
Java Jedis
以Python为例,首先安装redis-py。
pip install redis
一个简单的测试代码如下,首先获得一个Sentinel对象,然后
1
2
3
4
5
6
7
vim sentinel.py
from redis.sentinel import Sentinel
sentinel = Sentinel([('localhost', 26379)], socket_timeout=0.1)
master = sentinel.master_for('myredis', socket_timeout=0.1)
master.set('foo', 'bar')
slave = sentinel.slave_for('myredis', socket_timeout=0.1)
slave.get('foo')
执行后成功得到bar这个值。
1
2
python sentinel.py
bar
上面的master和slave都是标准的建立好连接的StrictRedis实例,slave则是sentinel查询到的第一个可用的slave。如果正在连接的master不可用时,客户端会先抛出redis.exceptions.ConnectionError异常(此时还没开始failover),然后抛出redis.sentinel.MasterNotFoundError异常(failover进行中),在sentinel正常failover之后,实例正常。所以要开发一个sentinel的高可用客户端,可以参考上面那篇官方的指导。

Redis Sentinel配置小记的更多相关文章

  1. redis sentinel 配置

    在最小配置:master.slave各一个节点的情况下,不管是master还是slave down掉一个,“完整的”读/写功能都将受影响,这在生产环境中显然不能接受.幸好redis提供了sentine ...

  2. Redis Sentinel 高可用服务搭建

    阅读目录: 关于 Redis 的概念 关于 Redis Sentinel 的概念 搭建 Redis Server(master) 搭建 Redis Server(slave) 搭建 Redis Sen ...

  3. 【转载】Redis Sentinel 高可用服务架构搭建

    作者:田园里的蟋蟀 出处:http://www.cnblogs.com/xishuai/ 本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接. 阅读 ...

  4. Redis 安装,主从配置及Sentinel配置自动Failover

    1.安装redis 首页地址:http://redis.io/ 下载地址:http://download.redis.io/ 下载最新的源码包 tar -zxvf redis-stable.tar.g ...

  5. redis sentinel集群配置及haproxy配置

    ip分布情况: sentinel-1/redis 主 10.11.11.5 sentinel-2/redis 从 10.11.11.7 sentinel-3/redis 从 10.11.11.8 ha ...

  6. laravel redis sentinel 和 redis cluster 配置

    laravel redis sentinel配置: 'redis' => [ 'cluster' => false, 'options' => [ 'replication' =&g ...

  7. Redis Sentinel主从高可用方案

    Redis Sentinel主从高可用方案 本文介绍一种通过Jed和Sentinel实现Redis集群(主从)的高可用方案,该方案需要使用Jedis2.2.2及以上版本(强制),Redis2.8及以上 ...

  8. spring集成redis——主从配置以及哨兵监控

    Redis主从模式配置: Redis的主从模式配置是非常简单的,首先我们需要有2个可运行的redis环境: master node : 192.168.56.101 8887 slave node: ...

  9. redis sentinel集群

    ip分布情况: sentinel-1/redis 主 10.11.11.5 sentinel-2/redis 从 10.11.11.7 sentinel-3/redis 从 10.11.11.8 ha ...

随机推荐

  1. java_多态

    一.多态(对象的多种形态)1.引用的多态 父类的引用指向本类的对象 父类的引用指向子类的对象(引用多态) (不允许子类对象指向父类)2.方法多态 创建本类对象时调用的方法为本类的方法 创建子类对象时, ...

  2. 【SqlServer】JSON函数

    1   概述 本篇文件将结合MSND简要分析Sqlserver中JSON函数,主要包括ISJSON,JSON_VALUE,JSON_MODIFY,JSON_QUERY. 2   具体内容 2.1  J ...

  3. jersey实现文件下载

    好久没有更新博客了,今天来再次总结一下,之前有整理过关于jersey实现文件上传功能的相关知识,但是前一阵子在实习过程中写接口又要实现文件下载的功能,由于这些东西基本都是使用jersey提供的注解和接 ...

  4. Postgres中的物化节点之sort节点

    顾名思义,物化节点是一类可缓存元组的节点.在执行过程中,很多扩展的物理操作符需要首先获取所有的元组后才能进行操作(例如聚集函数操作.没有索引辅助的排序等),这时要用物化节点将元组缓存起来.下面列出了P ...

  5. springboot 结合mybatis

    MyBatis 是一款优秀的持久层框架,它支持定制化 SQL.存储过程以及高级映射.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以使用简单的 XML ...

  6. mouseout、mouseover和mouseleave、mouseenter区别

    今天在使用鼠标事件时,用错了mouseout,于是做个测试总结. 结论: mouseenter:当鼠标移入某元素时触发. mouseleave:当鼠标移出某元素时触发. mouseover:当鼠标移入 ...

  7. ArcGIS 网络分析[2.2] 服务区分析

    什么是服务区? 我们先提一个很常见的社会现象:一个医院,如果要发起抢救,那么10分钟内能去多远? 时间就是生命,当结合道路网的阻力进行最短路径分析时,得到的可达的覆盖区域,这个区域就是服务区. 服务区 ...

  8. express整合webpack的打包文件dist

    对于我来说,第一次接触前后端整合问题的小白,刚开始是一脸懵逼,这个问题整整坑了我一个晚上加一个早上,现在写出来总结: 前端开发:vue-cli+webpack: 后台开发:nodejs框架expres ...

  9. 使用 Kafka 和 ELK 搭建测试日志系统(1)

    本文仅供自己学习,不合适转载. 这是两篇文章的第一部分. 1. 安装 ELK 1.1 安装 ElasticSearch 在海航云上创建一个 Ubutu 16.4 虚机,2核4GB内存. (1)执行以下 ...

  10. uptime 命令详解

    作用: 打印系统总共运行了多长时间和系统的平均负载. uptime 命令可以显示的信息依次为:  现在时间, 系统已经运行时间, 目前登录用户个数, 系统1,5,15 分钟内的平均负载 实例:  up ...