墨墨导读:本文在依托Redis主从环境下,针对访问的数据一致性进行分析,解开Redis复制原理的神秘面纱。
Redis作为一个非结构化的内存数据库,在某些应用场景具备相应优势,在实际的场景设计中也得到广泛的关注和使用。但是,大部分企业的Redis数据库架构为单机运行,没有设计容灾复制,这样对于Redis的容错特性没有发挥出来,而且无持久化情况下,数据存在丢失风险。
[redis@albert redis-5.0.4]$ cp redis.conf redis.conf6380
################################# REPLICATION #################################
# Master-Replica replication. Use replicaof to make a Redis instance a copy of
# another Redis server. A few things to understand ASAP about Redis replication.
#
# +------------------+ +---------------+
# | Master | ---> | Replica |
# | (receive writes) | | (exact copy) |
# +------------------+ +---------------+
#
# 1) Redis replication is asynchronous, but you can configure a master to
# stop accepting writes if it appears to be not connected with at least
# a given number of replicas.
# 2) Redis replicas are able to perform a partial resynchronization with the
# master if the replication link is lost for a relatively small amount of
# time. You may want to configure the replication backlog size (see the next
# sections of this file) with a sensible value depending on your needs.
# 3) Replication is automatic and does not need user intervention. After a
# network partition replicas automatically try to reconnect to masters
# and resynchronize with them.
#
# replicaof
# slaveof
slaveof 127.0.0.1 6379
[redis@albert src]$ ./redis-server redis.conf6380
18828:C 04 Aug 2019 10:52:27.743 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
18828:C 04 Aug 2019 10:52:27.744 # Redis version=5.0.4, bits=64, commit=00000000, modified=0, pid=18828, just started
18828:C 04 Aug 2019 10:52:27.744 # Configuration loaded
_._
_.-``__ ''-._
_.-`` `. `_. ''-._ Redis 5.0.4 (00000000/0) 64 bit
.-`` .-```. ```\/ _.,_ ''-._
( ' , .-` | `, ) Running in standalone mode
|`-._`-...-` __...-.``-._|'` _.-'| Port: 6380
| `-._ `._ / _.-' | PID: 18828
`-._ `-._ `-./ _.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' | http://redis.io
`-._ `-._`-.__.-'_.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' |
`-._ `-._`-.__.-'_.-' _.-'
`-._ `-.__.-' _.-'
`-._ _.-'
`-.__.-'
18828:S 04 Aug 2019 10:52:27.746 # Server initialized
18828:S 04 Aug 2019 10:52:27.746 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
18828:S 04 Aug 2019 10:52:27.746 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.
18828:S 04 Aug 2019 10:52:27.746 * Ready to accept connections
18828:S 04 Aug 2019 10:52:27.746 * Connecting to MASTER 127.0.0.1:6379
18828:S 04 Aug 2019 10:52:27.746 * MASTER <-> REPLICA sync started
18828:S 04 Aug 2019 10:52:27.746 * Non blocking connect for SYNC fired the event.
18828:S 04 Aug 2019 10:52:27.746 * Master replied to PING, replication can continue...
18828:S 04 Aug 2019 10:52:27.747 * Partial resynchronization not possible (no cached master)
18828:S 04 Aug 2019 10:52:27.748 * Full resync from master: fc71b19242e8145254ba7751d346a8f4bb4c53c6:0
18828:S 04 Aug 2019 10:52:27.788 * MASTER <-> REPLICA sync: receiving 175 bytes from master
18828:S 04 Aug 2019 10:52:27.788 * MASTER <-> REPLICA sync: Flushing old data
18828:S 04 Aug 2019 10:52:27.788 * MASTER <-> REPLICA sync: Loading DB in memory
18828:S 04 Aug 2019 10:52:27.788 * MASTER <-> REPLICA sync: Finished with success
18661:M 04 Aug 2019 10:52:27.747 * Replica 127.0.0.1:6380 asks for synchronization
18661:M 04 Aug 2019 10:52:27.747 * Full resync requested by replica 127.0.0.1:6380
18661:M 04 Aug 2019 10:52:27.747 * Starting BGSAVE for SYNC with target: disk
18661:M 04 Aug 2019 10:52:27.747 * Background saving started by pid 18832
18832:C 04 Aug 2019 10:52:27.757 * DB saved on disk
18832:C 04 Aug 2019 10:52:27.757 * RDB: 4 MB of memory used by copy-on-write
18661:M 04 Aug 2019 10:52:27.788 * Background saving terminated with success
18661:M 04 Aug 2019 10:52:27.788 * Synchronization with replica 127.0.0.1:6380 succeeded
[redis@albert src]$ ./redis-cli -p 6380
127.0.0.1:6380>
127.0.0.1:6380>
127.0.0.1:6380> INFO replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6379
master_link_status:up
master_last_io_seconds_ago:6
master_sync_in_progress:0
slave_repl_offset:252
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:fc71b19242e8145254ba7751d346a8f4bb4c53c6
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:252
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:252
[redis@albert src]$ ./redis-cli -p 6379
127.0.0.1:6379> INFO replication
# Replication
role:master
connected_slaves:1
slave0:ip=127.0.0.1,port=6380,state=online,offset=364,lag=0
master_replid:fc71b19242e8145254ba7751d346a8f4bb4c53c6
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:364
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:364
127.0.0.1:6379> set kebo 24
OK
127.0.0.1:6380> get kebo
"24"
33570:S 26 Aug 2019 11:54:48.918 * Ready to accept connections
33570:S 26 Aug 2019 11:54:48.918 * Connecting to MASTER 127.0.0.1:6379
33570:S 26 Aug 2019 11:54:48.918 * MASTER <-> REPLICA sync started
33570:S 26 Aug 2019 11:54:48.918 * Non blocking connect for SYNC fired the event.
33570:S 26 Aug 2019 11:54:48.918 * Master replied to PING, replication can continue...
33570:S 26 Aug 2019 11:54:48.918 * Trying a partial resynchronization (request fc71b19242e8145254ba7751d346a8f4bb4c53c6:2533).
33570:S 26 Aug 2019 11:54:48.920 * Full resync from master: b9e0f41a523e078a6a88ae274f204777775ab4dc:0
33570:S 26 Aug 2019 11:54:48.920 * Discarding previously cached master state.
33570:S 26 Aug 2019 11:54:49.003 * MASTER <-> REPLICA sync: receiving 188 bytes from master
33570:S 26 Aug 2019 11:54:49.003 * MASTER <-> REPLICA sync: Flushing old data
33570:S 26 Aug 2019 11:54:49.003 * MASTER <-> REPLICA sync: Loading DB in memory
33570:S 26 Aug 2019 11:54:49.004 * MASTER <-> REPLICA sync: Finished with success
33565:M 26 Aug 2019 11:54:48.918 * Replica 127.0.0.1:6380 asks for synchronization
33565:M 26 Aug 2019 11:54:48.918 * Partial resynchronization not accepted: Replication ID mismatch (Replica asked for 'fc71b19242e8145254ba7751d346a8f4bb4c53c6', my replication IDs are '1e531f295fc2dcf986a18889e8f8c3b6e6fdc7b6' and '0000000000000000000000000000000000000000')
33565:M 26 Aug 2019 11:54:48.918 * Starting BGSAVE for SYNC with target: disk
33565:M 26 Aug 2019 11:54:48.919 * Background saving started by pid 33574
33574:C 26 Aug 2019 11:54:48.929 * DB saved on disk
33574:C 26 Aug 2019 11:54:48.929 * RDB: 4 MB of memory used by copy-on-write
33565:M 26 Aug 2019 11:54:49.002 * Background saving terminated with success
33565:M 26 Aug 2019 11:54:49.003 * Synchronization with replica 127.0.0.1:6380 succeeded
[redis@albert src]$ ps -ef | grep redis
redis 33565 33500 0 11:54 pts/4 00:00:01 ./redis-server *:6379
redis 33570 33476 0 11:54 pts/5 00:00:01 ./redis-server 127.0.0.1:6380
redis 33744 33688 0 12:03 pts/0 00:00:00 ./redis-server 127.0.0.1:6382
[redis@albert src]$
[redis@albert src]$ kill -9 33744
33565:M 26 Aug 2019 12:03:17.736 * Replica 127.0.0.1:6382 asks for synchronization
33565:M 26 Aug 2019 12:03:17.736 * Partial resynchronization request from 127.0.0.1:6382 accepted. Sending 714 bytes of backlog starting from offset 1.
33565:M 26 Aug 2019 12:13:43.494 # Connection with replica 127.0.0.1:6382 lost.
33565:M 26 Aug 2019 12:14:12.019 * Replica 127.0.0.1:6382 asks for synchronization
33565:M 26 Aug 2019 12:14:12.019 * Partial resynchronization request from 127.0.0.1:6382 accepted. Sending 436 bytes of backlog starting from offset 1315.
role:master
connected_slaves:2
slave0:ip=127.0.0.1,port=6380,state=online,offset=3724,lag=1
slave1:ip=127.0.0.1,port=6382,state=online,offset=3724,lag=1
master_replid:b9e0f41a523e078a6a88ae274f204777775ab4dc
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:3724
second_repl_offset:-1
repl_backlog_active:1
role:slave
master_host:127.0.0.1
master_port:6379
master_link_status:up
master_last_io_seconds_ago:7
master_sync_in_progress:0
slave_repl_offset:3752
slave_priority:100
slave_read_only:1
[redis@albert src]$ cp redis.conf6380 redis.conf6382
[redis@albert src]$ ./redis-server redis.conf6382
33744:C 26 Aug 2019 12:03:17.731 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
33744:C 26 Aug 2019 12:03:17.731 # Redis version=5.0.4, bits=64, commit=00000000, modified=0, pid=33744, just started
33744:C 26 Aug 2019 12:03:17.731 # Configuration loaded
_._
_.-``__ ''-._
_.-`` `. `_. ''-._ Redis 5.0.4 (00000000/0) 64 bit
.-`` .-```. ```\/ _.,_ ''-._
( ' , .-` | `, ) Running in standalone mode
|`-._`-...-` __...-.``-._|'` _.-'| Port: 6382
| `-._ `._ / _.-' | PID: 33744
`-._ `-._ `-./ _.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' | http://redis.io
`-._ `-._`-.__.-'_.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' |
`-._ `-._`-.__.-'_.-' _.-'
`-._ `-.__.-' _.-'
`-._ _.-'
`-.__.-'
33744:S 26 Aug 2019 12:03:17.734 # Server initialized
33744:S 26 Aug 2019 12:03:17.734 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
33744:S 26 Aug 2019 12:03:17.734 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.
33744:S 26 Aug 2019 12:03:17.734 * DB loaded from disk: 0.000 seconds
33744:S 26 Aug 2019 12:03:17.734 * Before turning into a replica, using my master parameters to synthesize a cached master: I may be able to synchronize with the new master with just a partial transfer.
33744:S 26 Aug 2019 12:03:17.734 * Ready to accept connections
33744:S 26 Aug 2019 12:03:17.735 * Connecting to MASTER 127.0.0.1:6379
33744:S 26 Aug 2019 12:03:17.735 * MASTER <-> REPLICA sync started
33744:S 26 Aug 2019 12:03:17.735 * Non blocking connect for SYNC fired the event.
33744:S 26 Aug 2019 12:03:17.735 * Master replied to PING, replication can continue...
33744:S 26 Aug 2019 12:03:17.736 * Trying a partial resynchronization (request b9e0f41a523e078a6a88ae274f204777775ab4dc:1).
33744:S 26 Aug 2019 12:03:17.736 * Successful partial resynchronization with master.
33744:S 26 Aug 2019 12:03:17.736 * MASTER <-> REPLICA sync: Master accepted a Partial Resynchronization.
# Replication
role:master
connected_slaves:2
slave0:ip=127.0.0.1,port=6380,state=online,offset=6986,lag=1
slave1:ip=127.0.0.1,port=6382,state=online,offset=6986,lag=0
127.0.0.1:6379> mset a 1 b 2 c 3 d 4
OK
127.0.0.1:6380> mget a b c d
1) "1"
2) "2"
3) "3"
4) "4"
127.0.0.1:6382> mget a b c d
1) "1"
2) "2"
3) "3"
4) "4"
127.0.0.1:6379> shutdown
33570:S 26 Aug 2019 13:23:41.429 * Connecting to MASTER 127.0.0.1:6379
33570:S 26 Aug 2019 13:23:41.429 * MASTER <-> REPLICA sync started
33570:S 26 Aug 2019 13:23:41.429 # Error condition on socket for SYNC: Connection refused
33570:S 26 Aug 2019 13:23:42.441 * Connecting to MASTER 127.0.0.1:6379
33570:S 26 Aug 2019 13:23:42.442 * MASTER <-> REPLICA sync started
33570:S 26 Aug 2019 13:23:42.442 # Error condition on socket for SYNC: Connection refused
33570:S 26 Aug 2019 13:23:43.455 * Connecting to MASTER 127.0.0.1:6379
33570:S 26 Aug 2019 13:23:43.456 * MASTER <-> REPLICA sync started
33570:S 26 Aug 2019 13:23:43.456 # Error condition on socket for SYNC: Connection refused
33570:S 26 Aug 2019 13:23:44.466 * Connecting to MASTER 127.0.0.1:6379
33570:S 26 Aug 2019 13:23:44.466 * MASTER <-> REPLICA sync started
33570:S 26 Aug 2019 13:23:44.466 # Error condition on socket for SYNC: Connection refused
33570:S 26 Aug 2019 13:23:45.470 * Connecting to MASTER 127.0.0.1:6379
33570:S 26 Aug 2019 13:23:45.471 * MASTER <-> REPLICA sync started
33570:S 26 Aug 2019 13:23:45.471 # Error condition on socket for SYNC: Connection refused
33570:S 26 Aug 2019 13:23:46.474 * Connecting to MASTER 127.0.0.1:6379
33570:S 26 Aug 2019 13:23:46.475 * MASTER <-> REPLICA sync started
33570:S 26 Aug 2019 13:23:46.475 # Error condition on socket for SYNC: Connection refused
33570:S 26 Aug 2019 13:23:47.478 * Connecting to MASTER 127.0.0.1:6379
33570:S 26 Aug 2019 13:23:47.478 * MASTER <-> REPLICA sync started
33570:S 26 Aug 2019 13:23:47.478 # Error condition on socket for SYNC: Connection refused
33570:S 26 Aug 2019 13:23:48.481 * Connecting to MASTER 127.0.0.1:6379
33570:S 26 Aug 2019 13:23:48.481 * MASTER <-> REPLICA sync started
33570:S 26 Aug 2019 13:23:48.481 # Error condition on socket for SYNC: Connection refused
33570:S 26 Aug 2019 13:23:49.485 * Connecting to MASTER 127.0.0.1:6379
33570:S 26 Aug 2019 13:23:49.485 * MASTER <-> REPLICA sync started
33570:S 26 Aug 2019 13:23:49.485 # Error condition on socket for SYNC: Connection refused
33570:S 26 Aug 2019 13:23:50.488 * Connecting to MASTER 127.0.0.1:6379
34781:M 26 Aug 2019 13:24:05.899 * DB loaded from disk: 0.000 seconds
34781:M 26 Aug 2019 13:24:05.899 * Ready to accept connections
34781:M 26 Aug 2019 13:24:06.544 * Replica 127.0.0.1:6380 asks for synchronization
34781:M 26 Aug 2019 13:24:06.544 * Partial resynchronization not accepted: Replication ID mismatch (Replica asked for 'b9e0f41a523e078a6a88ae274f204777775ab4dc', my replication IDs are 'aac4a31754592820422c3ba7c8244f31c39f067f' and '0000000000000000000000000000000000000000')
34781:M 26 Aug 2019 13:24:06.544 * Starting BGSAVE for SYNC with target: disk
34781:M 26 Aug 2019 13:24:06.545 * Background saving started by pid 34785
34785:C 26 Aug 2019 13:24:06.555 * DB saved on disk
34785:C 26 Aug 2019 13:24:06.555 * RDB: 4 MB of memory used by copy-on-write
34781:M 26 Aug 2019 13:24:06.601 * Background saving terminated with success
34781:M 26 Aug 2019 13:24:06.602 * Synchronization with replica 127.0.0.1:6380 succeeded
34781:M 26 Aug 2019 13:24:06.642 * Replica 127.0.0.1:6382 asks for synchronization
34781:M 26 Aug 2019 13:24:06.642 * Partial resynchronization not accepted: Replication ID mismatch (Replica asked for 'b9e0f41a523e078a6a88ae274f204777775ab4dc', my replication IDs are 'd41f950be7593a93620b1fd872b7552668f0b355' and '0000000000000000000000000000000000000000')
34781:M 26 Aug 2019 13:24:06.642 * Starting BGSAVE for SYNC with target: disk
34781:M 26 Aug 2019 13:24:06.643 * Background saving started by pid 34786
34786:C 26 Aug 2019 13:24:06.644 * DB saved on disk
34786:C 26 Aug 2019 13:24:06.644 * RDB: 4 MB of memory used by copy-on-write
34781:M 26 Aug 2019 13:24:06.701 * Background saving terminated with success
34781:M 26 Aug 2019 13:24:06.701 * Synchronization with replica 127.0.0.1:6382 succeeded
33570:S 26 Aug 2019 13:24:06.544 * Master replied to PING, replication can continue...33570:S 26 Aug 2019 13:24:06.544 * Master replied to PING, replication can continue...
33570:S 26 Aug 2019 13:24:06.544 * Trying a partial resynchronization (request b9e0f41a523e078a6a88ae274f204777775ab4dc:7603).
33570:S 26 Aug 2019 13:24:06.545 * Full resync from master: d41f950be7593a93620b1fd872b7552668f0b355:0
33570:S 26 Aug 2019 13:24:06.545 * Discarding previously cached master state.
33570:S 26 Aug 2019 13:24:06.601 * MASTER <-> REPLICA sync: receiving 240 bytes from master
33570:S 26 Aug 2019 13:24:06.601 * MASTER <-> REPLICA sync: Flushing old data
33570:S 26 Aug 2019 13:24:06.601 * MASTER <-> REPLICA sync: Loading DB in memory
33570:S 26 Aug 2019 13:24:06.601 * MASTER <-> REPLICA sync: Finished with success
127.0.0.1:6382> shutdown
not connected>
34781:M 26 Aug 2019 13:24:06.701 * Synchronization with replica 127.0.0.1:6382 succeeded
34781:M 26 Aug 2019 13:29:45.037 # Connection with replica 127.0.0.1:6382 lost.
# Replication
role:master
connected_slaves:1
slave0:ip=127.0.0.1,port=6380,state=online,offset=546,lag=1
127.0.0.1:6379> set slavetest 0851
OK
127.0.0.1:6380> keys *
1) "test02"
2) "c"
3) "d"
4) "a"
5) "test"
6) "kebo"
7) "slavetest"
8) "b"
9) "redisfast"
127.0.0.1:6380> get slavetest
"0851"
34855:S 26 Aug 2019 13:34:39.561 * DB loaded from disk: 0.000 seconds
34855:S 26 Aug 2019 13:34:39.561 * Before turning into a replica, using my master parameters to synthesize a cached master: I may be able to synchronize with the new master with just a partial transfer.
34855:S 26 Aug 2019 13:34:39.561 * Ready to accept connections
34855:S 26 Aug 2019 13:34:39.561 * Connecting to MASTER 127.0.0.1:6379
34855:S 26 Aug 2019 13:34:39.561 * MASTER <-> REPLICA sync started
34855:S 26 Aug 2019 13:34:39.561 * Non blocking connect for SYNC fired the event.
34855:S 26 Aug 2019 13:34:39.561 * Master replied to PING, replication can continue...
34855:S 26 Aug 2019 13:34:39.562 * Trying a partial resynchronization (request d41f950be7593a93620b1fd872b7552668f0b355:888).
34855:S 26 Aug 2019 13:34:39.562 * Successful partial resynchronization with master.
34855:S 26 Aug 2019 13:34:39.562 * MASTER <-> REPLICA sync: Master accepted a Partial Resynchronization.
34781:M 26 Aug 2019 13:24:06.701 * Synchronization with replica 127.0.0.1:6382 succeeded
34781:M 26 Aug 2019 13:29:45.037 # Connection with replica 127.0.0.1:6382 lost.
34781:M 26 Aug 2019 13:34:39.562 * Replica 127.0.0.1:6382 asks for synchronization
34781:M 26 Aug 2019 13:34:39.562 * Partial resynchronization request from 127.0.0.1:6382 accepted. Sending 56 bytes of backlog starting from offset 888.
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=127.0.0.1,port=6380,state=online,offset=1139,lag=1
slave1:ip=127.0.0.1,port=6382,state=online,offset=1139,lag=1
master_replid:d41f950be7593a93620b1fd872b7552668f0b355
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:1139
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:1139
出处:墨天轮(https://www.modb.pro/db/6415,复制到网页中打开或者点击“阅读原文”)
DBASK,DBA的即时问答平台
扩展阅读
AWR 报告深度解读:Redo Nowait指标的算法和诊断
国外数据库十大风云人物,你认识几个?
如何手工配置DBControl
项目上线后,谈一下感触比较深的一点:查询优化
数据安全警示录:XKCD论坛在56万会员数据泄露后关闭,密码安全应提升
MySQL EXPLAIN结果集分析 - 附带大量案例
2019年9月数据库流行度排行:MySQL 强劲增长完成深 V 反转
这个火热的社区都升级到2.0了,你还不知道它?
墨天轮“我的DBA之路”有奖征文开始啦
不会SQL注入,连漫画都看不懂了
数据和云
ID:OraNews
如有收获,请划至底部,点击“在看”,谢谢!
公司简介 | 招聘 | DTCC | 数据技术嘉年华 | 免费课程 | 入驻华为严选商城
zCloud | SQM | Bethune Pro2 | zData一体机 | MyData一体机 | ZDBM 备份一体机
Oracle技术架构 | 免费课程 | 数据库排行榜 | DBASK问题集萃 | 技术通讯
升级迁移 | 性能优化 | 智能整合 | 安全保障 | 架构设计 | SQL审核 | 分布式架构 | 高可用容灾 | 运维代维
云和恩墨大讲堂 | 一个分享交流的地方
长按,识别二维码,加入万人交流社群
请备注:云和恩墨大讲堂