Redis Sentinel 高可用服务架构搭建

阅读目录:

关于 Redis 的概念

关于 Redis Sentinel 的概念

搭建 Redis Server(master)

搭建 Redis Server(slave)

搭建 Redis Sentinel

Redis Sentinel 故障转移测试

前几天,看到了一篇文章:高可用 Redis 服务架构分析与搭建,思路讲的非常好,但是没有搭建的过程,这篇文章就记录下 Redis Sentinel 高可用服务架构搭建的过程。

搭建方案,就按照作者的第四种方案:

1. 关于 Redis 的概念

Redis 是完全开源免费的,遵守 BSD 协议,是一个高性能的 key-value 数据库。

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

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 的所有操作都是原子性的,意思就是要么成功执行要么失败完全不执行。单个操作是原子性的。多个操作也支持事务,即原子性,通过 MULTI 和 EXEC 指令包起来。

丰富的特性 – Redis 还支持 publish/subscribe, 通知, key 过期等等特性。

以上内容摘自:http://www.runoob.com/redis/redis-intro.html

2. 关于 Redis Sentinel 的概念

Redis Sentinel(译为“哨兵”)是 Redis 官方推荐的高可用性(HA)解决方案,当用 Redis 做 Master-slave 的高可用方案时,假如 master 宕机了,Redis 本身(包括它的很多客户端)都没有实现自动进行主备切换,而 Redis-sentinel 本身也是一个独立运行的进程,它能监控多个 master-slave 集群,发现 master 宕机后能进行自动切换。

Redis Sentinel 系统用于管理多个 Redis 服务器(instance),该系统执行以下三个任务:

监控(Monitoring):Sentinel 会不断地检查你的主服务器和从服务器是否运作正常。

提醒(Notification):当被监控的某个 Redis 服务器出现问题时,Sentinel 可以通过 API 向管理员或者其他应用程序发送通知。

自动故障迁移(Automatic failover):当一个主服务器不能正常工作时,Sentinel 会开始一次自动故障迁移操作,它会将失效主服务器的其中一个从服务器升级为新的主服务器,并让失效主服务器的其他从服务器改为复制新的主服务器;当客户端试图连接失效的主服务器时,集群也会向客户端返回新主服务器的地址,使得集群可以使用新主服务器代替失效服务器。

Redis Sentinel 是一个分布式系统,你可以在一个架构中运行多个 Sentinel 进程(progress),这些进程使用流言协议(gossip protocols)来接收关于主服务器是否下线的信息,并使用投票协议(agreement protocols)来决定是否执行自动故障迁移,以及选择哪个从服务器作为新的主服务器。

一个 Sentinel 进程可以与其他多个 Sentinel 进程进行连接,每个 Sentinel 进程之间可以互相检查对方的可用性,并进行信息交换。

以上内容摘自:http://redisdoc.com/topic/sentinel.html

3. 搭建 Redis Server(master)

我们就按照上面的架构图进行搭建,大概三台服务器(防火墙关闭):

10.9.10.154 master  redis-server redis-sentinel

10.9.10.152 slave    redis-server redis-sentinel

10.9.10.215 redis-sentinel

先从 redis.io/releases,下载最新版本的 Redis(需要进行编译)。

$ wget http://download.redis.io/releases/redis-4.0.8.tar.gz$ tar xzf redis-4.0.8.tar.gz$cdredis-4.0.8$ ls00-RELEASENOTES  COPYING    Makefile  redis.conf      runtest-sentinel  testsBUGS            INSTALL    README.md  runtest          sentinel.conf    utilsCONTRIBUTING    MANIFESTO  deps      runtest-cluster  src$cdsrc$ make install    CC Makefile.dep    INSTALL redis-sentinel    CC redis-cli.o    LINK redis-cli    CC redis-benchmark.o    LINK redis-benchmark    INSTALL redis-check-rdbHint: It's a good idea to run 'maketest' ;)

    INSTALL install

    INSTALL install

    INSTALL install

    INSTALL install

    INSTALL install

编译成功后,会在redis-4.0.8/src目录下,生成redis-server和redis-sentinel可执行文件。

然后,我们在 master 节点(10.9.10.154)上,创建redis-4.0.8/redis-master.conf配置文件,示例配置:

# 使用守护进程模式daemonize yes# 非保护模式,可以外网访问protected-mode no# 端口号port 6379# 绑定ip,本机的ipbind10.9.10.154# 学习开发,使用最大日志级别,能够看到最多的日志信息loglevel debug# 指定日志文件路径,没有文件的话,先创建logfile /home/ubuntu/redis/redis-4.0.8/redis-server.log# 客户端访问,需要密码连接requirepass 123456

然后启动 master:

$ src/redis-server redis-master.config$ cat redis-server.log8517:C 28 Feb 06:10:38.345# oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo8517:C 28 Feb 06:10:38.345# Redis version=4.0.8, bits=64, commit=00000000, modified=0, pid=8517, just started8517:C 28 Feb 06:10:38.345# Configuration loaded8518:M 28 Feb 06:10:38.349 * Increased maximum number of open files to 10032 (it was originallysetto 1024).8518:M 28 Feb 06:10:38.352 * Running mode=standalone, port=6379.8518:M 28 Feb 06:10:38.352# WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.8518:M 28 Feb 06:10:38.352# Server initialized8518:M 28 Feb 06:10:38.352# 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.8518:M 28 Feb 06:10:38.352 * Ready to accept connections8518:M 28 Feb 06:10:38.352 - 0 clients connected (0 slaves), 765776 bytesinuse

查看 Redis 的状态:

$ redis-cli -h 10.9.10.154 -p 6379 -a 12345610.9.10.154:6379> INFO replication# Replicationrole:masterconnected_slaves:0master_replid:7f90fb4ba0c2c450b184a348f23f31d9c40b010dmaster_replid2:0000000000000000000000000000000000000000master_repl_offset:0second_repl_offset:-1repl_backlog_active:0repl_backlog_size:1048576repl_backlog_first_byte_offset:0repl_backlog_histlen:010.9.10.154:6379> pingPONG

添加和获取键值测试:

10.9.10.154:6379>settesthelloOK10.9.10.154:6379> gettest"hello"

Redis 常用命令:

启动服务:service redis start

停止服务:service redis stop

重启服务:service ngredisnx restart

如果没有配置为 Service 服务,可以用下面命令关闭 Redis:

$ src/redis-cli shutdown或者$ ps aux | grep redis$kill111

4. 搭建 Redis Server(slave)

slave 节点和 master 节点搭建差不多,只不过redis-slave.conf配置文件,有些不同:

# 使用守护进程模式daemonize yes# 非保护模式,可以外网访问protected-mode no# 端口号port 6379# 绑定ip,本机的ipbind10.9.10.152# 指定 master 的 ip 地址和端口slaveof 10.9.10.154 6379# 学习开发,使用最大日志级别,能够看到最多的日志信息loglevel debug# 指定日志文件路径,没有文件的话,先创建logfile /home/ubuntu/redis/redis-4.0.8/redis-server.log# 设置访问 master 的密码masterauth 123456

然后启动 slave:

$ src/redis-server redis-slave.conf$ cat redis-server.log7307:C 28 Feb 06:11:00.987# oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo7307:C 28 Feb 06:11:00.987# Redis version=4.0.8, bits=64, commit=00000000, modified=0, pid=7307, just started7307:C 28 Feb 06:11:00.987# Configuration loaded7308:S 28 Feb 06:11:00.989 * Increased maximum number of open files to 10032 (it was originallysetto 1024).7308:S 28 Feb 06:11:00.989 * Running mode=standalone, port=6379.7308:S 28 Feb 06:11:00.990# WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.7308:S 28 Feb 06:11:00.990# Server initialized7308:S 28 Feb 06:11:00.990# 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.7308:S 28 Feb 06:11:00.990 * Ready to accept connections7308:S 28 Feb 06:11:00.990 - 0 clients connected (0 slaves), 765736 bytesinuse7308:S 28 Feb 06:11:00.990 * Connecting to MASTER 10.9.10.154:63797308:S 28 Feb 06:11:00.990 * MASTER <-> SLAVE sync started7308:S 28 Feb 06:11:00.990 * Non blocking connectforSYNC fired the event.7308:S 28 Feb 06:11:00.991 * Master replied to PING, replication cancontinue...7308:S 28 Feb 06:11:00.993 * Partial resynchronization not possible (no cached master)7308:S 28 Feb 06:11:00.995 * Full resync from master: 55b29a9f06ffb89f96106287ce95ddfbdeccb986:0

查看 Redis 的状态:

$ redis-cli -h 10.9.10.152 -p 6379 -a 12345610.9.10.154:6379> INFO replication# Replicationrole:slavemaster_host:10.9.10.154master_port:6379master_link_status:upmaster_last_io_seconds_ago:10master_sync_in_progress:0slave_repl_offset:280slave_priority:100slave_read_only:1connected_slaves:0master_replid:55b29a9f06ffb89f96106287ce95ddfbdeccb986master_replid2:0000000000000000000000000000000000000000master_repl_offset:280second_repl_offset:-1repl_backlog_active:1repl_backlog_size:1048576repl_backlog_first_byte_offset:1repl_backlog_histlen:28010.9.10.152:6379> pingPONG

然后我们再查看下 master 的状态(更新了connected_slaves的信息):

$ redis-cli -h 10.9.10.154 -p 6379 -a 12345610.9.10.154:6379> INFO replication# Replicationrole:masterconnected_slaves:1slave0:ip=10.9.10.152,port=6379,state=online,offset=28,lag=1master_replid:55b29a9f06ffb89f96106287ce95ddfbdeccb986master_replid2:0000000000000000000000000000000000000000master_repl_offset:28second_repl_offset:-1repl_backlog_active:1repl_backlog_size:1048576repl_backlog_first_byte_offset:1repl_backlog_histlen:28

另外,你可以测试下,在 master 上添加一个 key 和 value,然后就可以在 salve 上获取这个对应的 key 的 value。

5. 搭建 Redis Sentinel

接着,我们分别在三台服务器上,配置 Redis Sentinel,创建redis-4.0.8/sentinel-my.conf配置文件,示例配置(记得更改不同的bind ip):

port 26379bind10.9.10.154daemonize yeslogfile /home/ubuntu/redis/redis-4.0.8/redis-sentinel.logsentinel monitor manager1 10.9.10.154 6379 2sentinel auth-pass manager1 123456sentinel down-after-milliseconds manager1 60000sentinel failover-timeout manager1 180000sentinel parallel-syncs manager1 1

这四行配置为一组,因为我们只有一个 master 节点,所以只配置了一个 master,可以配置多个 master,不用配置 slave 的信息,因为 slave 能够被自动检测到(master 节点会有关于 slave 的消息)

第一行配置指示 Sentinel 去监视一个名为manager1的主服务器,这个主服务器的 IP 地址为10.9.10.154,端口号为 6379,而将这个主服务器判断为失效至少需要 2 个 Sentinel 同意(只要同意 Sentinel 的数量不达标,自动故障迁移就不会执行)。

其他选项的基本格式如下:

sentinel <选项的名字> <主服务器的名字> <选项的值>

选项说明:

auth-pass:选项指定了 master 的连接密码。

down-after-milliseconds:选项指定了 Sentinel 认为服务器已经断线所需的毫秒数。

failover-timeout:如果在该时间(ms)内未能完成 failover 操作,则认为该 failover 失败。

parallel-syncs:选项指定了在执行故障转移时,最多可以有多少个从服务器同时对新的主服务器进行同步,这个数字越小,完成故障转移所需的时间就越长。

接着,我们启动 Redis Sentinel(默认端口 26379):

$ src/redis-server sentinel-my.conf --sentinel或者$ src/redis-sentinel sentinel-my.conf$ cat redis-sentinel.log5716:X 28 Feb 03:04:17.407# oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo5716:X 28 Feb 03:04:17.407# Redis version=4.0.8, bits=64, commit=00000000, modified=0, pid=5716, just started5716:X 28 Feb 03:04:17.407# Configuration loaded5716:X 28 Feb 03:04:17.408 * Increased maximum number of open files to 10032 (it was originallysetto 1024).                _._          _.-``__''-._      _.-``    `.  `_.''-._          Redis 4.0.8 (00000000/0) 64 bit  .-`` .-```.  ```\/    _.,_''-._ ('      ,      .-`  | `,    )    Running in sentinel mode

|`-._`-...-` __...-.``-._|'` _.-'|    Port: 26379

|    `-._  `._    /    _.-'|    PID: 5716  `-._    `-._  `-./  _.-'    _.-'|`-._`-._    `-.__.-'    _.-'_.-'|

|    `-._`-._        _.-'_.-'    |          http://redis.io

  `-._    `-._`-.__.-'_.-'    _.-'|`-._`-._    `-.__.-'    _.-'_.-'|

|    `-._`-._        _.-'_.-'    |

  `-._    `-._`-.__.-'_.-'    _.-'`-._    `-.__.-'    _.-'`-._        _.-'

              `-.__.-'5716:X 28 Feb 03:04:17.410# WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.5716:X 28 Feb 03:04:17.412# Sentinel ID is 493852dd16017dccdf7b169a256ce7eea2719aff5716:X 28 Feb 03:04:17.412# +monitor master manager1 10.9.10.154 6379 quorum 2

当有其他服务器启动 Redis Sentinel 的时候,会有这样的日志(Redis Sentinel 是会相互通信的):

5716:X28Feb03:18:46.404#-tilt#tiltmodeexited5716:X28Feb03:19:43.959* +sentinelsentinel55ebce153ac69c908800bc14beff24725fc5a72110.9.10.15226379 @ manager110.9.10.1546379

连接测试(测试三台服务器):

$ redis-cli -h 10.9.10.154 -p 26379

10.9.10.154:6379> ping

PONG

$ redis-cli -h 10.9.10.152 -p 26379

10.9.10.152:6379> ping

PONG

$ redis-cli -h 10.9.10.155 -p 26379

10.9.10.155:6379> ping

PONG

其他常用命令:

PING - 这个命令简单的返回 PONE。

SENTINEL masters - 展示监控的 master 清单和它们的状态。

SENTINEL master [master name] - 展示指定 master 的状态和信息。

SENTINEL slaves [master name] - 展示 master 的 slave 清单和它们的状态。

SENTINEL sentinels [master name] - 展示 master 的 sentinel 实例的清单和它们的状态。

SENTINEL get-master-addr-by-name [master name] - 返回 master 的 IP 和端口。如果故障转移在处理中或成功终止,返回晋升的 slave 的 IP 和端口。

SENTINEL reset [pattern] - 这个命令将重置所有匹配名字的 masters。参数是 blog 风格的。重置的过程清空 master 的所有状态,并移除已经发现和关联 master 的所有 slave 和 sentinel。

SENTINEL failover [master name] - 如果 master 不可到达,强制执行一个故障转移,而不征求其他 Sentinel 的同意。

SENTINEL ckquorum [master name] - 检查当前的 Sentinel 配置是否能够到达故障转移需要的法定人数,并且需要授权故障转移的多数。这个命令应该用于监控系统检查部署是否正确。

SENTINEL flushconfig - 强制 Sentinel 在磁盘上重写它的配置,包括当前的 Sentinel 状态。通常 Sentinel 每次重写配置改变它的状态。然而有时由于操作错误、硬盘故障、包升级脚本或配置管理器可能导致配置文件丢失。在这种情况下收到强制 Sentinel 重写配置文件。这个命令即使上面的配置文件完全不见了。

6. Redis Sentinel 故障转移测试

我们的计划是,将 master 的 Redis 服务停掉,看看 Redis Sentinel 是如何操作的。

首先,我们先查看下目前 master 节点的信息(记住 IP):

$ redis-cli -h 10.9.10.154 -p 637910.9.10.154:26379> SENTINEL get-master-addr-by-name manager11)"10.9.10.154"2)"6379"

然后执行下面命令(强制 Redis Server 休眠 120 秒):

$ redis-cli -h 10.9.10.154 -p 6379 -a 123456 DEBUG sleep 120

然后我们再查看下 master 节点的信息:

$ redis-cli -h 10.9.10.154 -p 637910.9.10.154:26379> SENTINEL get-master-addr-by-name manager11)"10.9.10.152"2)"6379"

发现 IP 已经变成了此前 salve 节点的,也就是说10.9.10.152变成了 master,然后我们查看下当前 master 的信息:

$ redis-cli -h 10.9.10.152 -p 6379 -a 12345610.9.10.152:6379> INFO replication# Replicationrole:masterconnected_slaves:1slave0:ip=10.9.10.154,port=6379,state=online,offset=1270535,lag=0master_replid:8b033de60b4be410a1706ff6b27b52b97bcc2981master_replid2:e56e893b96e7df8fda00ebcacf1d4b24c9499c4amaster_repl_offset:1270535second_repl_offset:1208143repl_backlog_active:1repl_backlog_size:1048576repl_backlog_first_byte_offset:221960repl_backlog_histlen:1048576

slave0:ip=10.9.10.154,port=6379表示此前的 master,已变为现在的 salve。

整个过程,我们可以查看 Redis Sentinel 的日志:

20153:X 28 Feb 09:13:51.023# +sdown master manager1 10.9.10.154 637920153:X 28 Feb 09:13:51.243# +new-epoch 120153:X 28 Feb 09:13:51.244# +vote-for-leader c14ac16f2a43c311c663677b7e056e744e2e2852 120153:X 28 Feb 09:13:52.102# +odown master manager1 10.9.10.154 6379 #quorum 2/220153:X 28 Feb 09:13:52.102# Next failover delay: I will not start a failover before Wed Feb 28 09:19:51 201820153:X 28 Feb 09:13:52.365# +config-update-from sentinel c14ac16f2a43c311c663677b7e056e744e2e2852 10.9.10.152 26379 @ manager1 10.9.10.154 637920153:X 28 Feb 09:13:52.365# +switch-master manager1 10.9.10.154 6379 10.9.10.152 637920153:X 28 Feb 09:13:52.365 * +slave slave 10.9.10.154:6379 10.9.10.154 6379 @ manager1 10.9.10.152 637920153:X 28 Feb 09:15:00.797 * +convert-to-slave slave 10.9.10.154:6379 10.9.10.154 6379 @ manager1 10.9.10.152 6379

翻译一下就是:

每个 Sentinel 发现了主节点挂掉了并有一个 +sdown 事件

这个事件稍候升级到 +odown,意味着大多数 Sentinel 已经同意了主节点是不可达的。

Sentinels 开始投票一个 Sentinel 开始并尝试故障转移

故障转移开始

另外,需要注意的是,Redis Sentinel 并不是提供对外服务的地址,它只是管理 Redis 主备切换的监测工具,所以,对外 Client 提供的地址,仍是 Redis Server 的地址(包含 salve),当然,也可以像提供负载均衡(SLB)或者虚拟IP(Virtual IP,VIP),进行统一地址的访问。

参考资料:

高可用 Redis 服务架构分析与搭建推荐

Redis 主从复制及 HA 环境搭建

Redis Sentinel 配置小记

Redis 哨兵-实现 Redis 高可用推荐

Sentinel推荐

Redis Sentinel 机制与用法(一)推荐

Redis 设置认证密码 Redis 使用认证密码登录 在 Redis 集群中使用认证密码

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 162,710评论 4 376
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,839评论 2 308
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 112,295评论 0 255
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,776评论 0 223
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 53,198评论 3 297
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 41,074评论 1 226
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,200评论 2 322
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,986评论 0 214
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,733评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,877评论 2 254
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,348评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,675评论 3 265
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,393评论 3 246
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,209评论 0 9
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,996评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,212评论 2 287
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 36,003评论 2 280

推荐阅读更多精彩内容