012、Redis主从复制的环境搭建
本文最后更新于 319 天前,其中的信息可能已经过时,如有错误请发送邮件到wuxianglongblog@163.com

Redis主从复制的环境搭建

一.Redis的作者antirez将"master-slave"架构的描述改为"master-replica"

    相信在座各位的开发者都不会对Redis的主从模式(master-slave)感到陌生。Redis中的主从模式事实上也是源自MySQL中同名的一个概念,是同步数据的一种手段。在这样的场景下,master-slave本来是一个不带任何政治感情色彩的词语。

    然而有很多开发者却不这样认为,他们在阅读 Redis 5.0 RC5 的变更日志后发现,Redis仍然在使用"master"和"slave"术语来在Redis的复制中区分不同的角色,他们对此感到失望,并希望Redis作者能修改Redis中master-slave架构的描述。

    Redis的作者antirez发文表示他很抱歉master-slave这个描述让许多人感到失望,但他不认为这个特定于上下文环境的术语具有侵犯性。所以他在数据库中使用master-slave当然不是以任何方式暗示"奴隶制度"。

    短期内的变化:
        (1)将"master-slave"架构的描述改为"master-replica";
        (2)为"SLAVEOF"提供别名"REPLICAOF",所以仍然可以使用 SLAVEOF,但多了一个选项;
        (3)保持继续使用"slave"来对"INFO"和"ROLE"进行回应,现在目前看来,这仍然是一个重大的破坏性变更;

    长期变化:
        (1)编写一个 INFO 的替代品
        (2)在内部替换很多东西,因为技术原因,如果作了改动,许多PR也会无法应用,所以必须在某些地方进行大变动

二.master-replica架构原理

1.master-replica架构工作原理

    如下图所示,是Redis的工作原理,其对应的文字说明如下:
        1>.replica库通过"SLAVEOF 172.200.1.201 6379"命令连接master库并发送"SYNC"给master库; 
        2>.master库收到"SYNC",会立即触发"BGSAVE"后台保存RDB快照,并将RDB快照发送给replica库;
        3>.replica库接收后会应用RDB快照;
        4>.master库会陆续将中间产生的新的操作保存并发送给replica库;
        5>.到此我们master复制集就正常工作了;
        6>.再此以后,master库只要发生新的操作,都会以命令传播的形式自动发送给replica库;
        7>.所有复制相关信息,从info信息中都可以查到,即使重启任何节点,他的master-replica关系依然都在;
        8>.如果发生master-replica关系断开时,replica库数据没有任何损坏,在下次重连之后,replica库发送"PSYNC"给master库;
        9>.master库只会将replica库缺失部分的数据同步给replica库应用,达到快速恢复master-replica架构的目的;

    温馨提示:(可能面试时会问到)
        (1)在Redis 2.8版本之前,如果master-replica架构中replica库宕机将会再次触发"SYNC",从而全量拷贝主库的数据,这样效率明显很低。于是在Redis 2.8版本之后就新增了"PSYNC"指令以实现可以理解为"断点续传"的功能。
        (2)生产环境中,建议开启master库持久化功能,避免因主库意外重启而导致缓存丢失。举个例子,master库右1w条数据,replica库在某一时刻仅有9k数据,还有1k数据未来得及同步master库时,master库意外重启导致KEY为0,此时replica库同步master库数据会将replica库已有的9k缓存数据删除以达到和master库同步的目的。

image-20210730123328473

2.主从数据一致性保证,类似于MySQL的半同步复制,了解即可。

    min-slaves-to-write 1
    min-slaves-max-lag  3

    参数说明:
        min-slaves-to-write:
            指定最小的的从库写入节点。
        min-slaves-max-lag:
            指定从库最小的延迟时间。

    温馨提示:
        上述两个参数均是为了保证数据写入的一致性,和MySQL的半同步复制有异曲同工之妙。
        综上所述,Redis的master-replica架构也不能100%保证数据的一致性。因为一旦"min-slaves-to-write"和"min-slaves-max-lag"就会都触发了,则由同步复制转换为异步复制。

3.面试题

    (1)PSYNC作用在哪?
        答:在Redis 2.8版本之后就新增了"PSYNC"指令以实现可以理解为"断点续传"的功能。不会像"SYNC"那样同步全部的数据,而是差异的部分进行数据同步。
    (2)主库是否要开启持久化?
        答:如果不开有可能,主库重启操作,造成所有主从数据丢失!

三.准备3个Redis实例部署master-replica架构实战

1.为各个Redis实例创建数据和配置文件目录

    (1)创建Redis的数据存储目录
        [root@redis201.oldboyedu.com ~]# mkdir -pv /oldboyedu/data/redis1637{0..2}
        mkdir: 已创建目录 "/oldboyedu/data/redis16370"
        mkdir: 已创建目录 "/oldboyedu/data/redis16371"
        mkdir: 已创建目录 "/oldboyedu/data/redis16372"
        [root@redis201.oldboyedu.com ~]# 

    (2)创建Redis的配置文件存储目录
        [root@redis201.oldboyedu.com ~]# mkdir -pv /oldboyedu/softwares/redis1637{0..2}
        mkdir: 已创建目录 "/oldboyedu/softwares/redis16370"
        mkdir: 已创建目录 "/oldboyedu/softwares/redis16371"
        mkdir: 已创建目录 "/oldboyedu/softwares/redis16372"
        [root@redis201.oldboyedu.com ~]# 

2.为各个Redis实例创建配置文件

    (1)为"redis16370"实例创建配置文件
        [root@redis201.oldboyedu.com ~]# cat > /oldboyedu/softwares/redis16370/redis.conf <<EOF
        > port 16370
        > daemonize yes
        > pidfile /oldboyedu/data/redis16370/redis.pid
        > loglevel notice
        > logfile /oldboyedu/data/redis16370/redis.log
        > dbfilename dump.rdb
        > dir /oldboyedu/data/redis16370
        > bind 172.200.1.201 127.0.0.1
        > requirepass oldboyedu
        > masterauth oldboyedu
        > # 配置RDB持久化策略
        > save 900 1
        > save 300 10
        > save 60 10000
        > # 配置AOF持久化
        > appendonly yes
        > appendfsync everysec
        > EOF
        [root@redis201.oldboyedu.com ~]# 
        [root@redis201.oldboyedu.com ~]# cat /oldboyedu/softwares/redis16370/redis.conf 
        port 16370
        daemonize yes
        pidfile /oldboyedu/data/redis16370/redis.pid
        loglevel notice
        logfile /oldboyedu/data/redis16370/redis.log
        dbfilename dump.rdb
        dir /oldboyedu/data/redis16370
        requirepass oldboyedu
        masterauth oldboyedu
        port 16370
        daemonize yes
        pidfile /oldboyedu/data/redis16370/redis.pid
        loglevel notice
        logfile /oldboyedu/data/redis16370/redis.log
        dbfilename dump.rdb
        dir /oldboyedu/data/redis16370
        bind 172.200.1.201 127.0.0.1
        requirepass oldboyedu
        masterauth oldboyedu
        # 配置RDB持久化策略
        save 900 1
        save 300 10
        save 60 10000
        # 配置AOF持久化
        appendonly yes
        appendfsync everysec
        [root@redis201.oldboyedu.com ~]# 

    (2)为"redis16371"实例创建配置文件
        [root@redis201.oldboyedu.com ~]# cat > /oldboyedu/softwares/redis16371/redis.conf <<EOF
        > port 16371
        > daemonize yes
        > pidfile /oldboyedu/data/redis16371/redis.pid
        > loglevel notice
        > logfile /oldboyedu/data/redis16371/redis.log
        > dbfilename dump.rdb
        > dir /oldboyedu/data/redis16371
        > bind 172.200.1.201 127.0.0.1
        > requirepass oldboyedu
        > masterauth oldboyedu
        > # 配置RDB持久化策略
        > save 900 1
        > save 300 10
        > save 60 10000
        > # 配置AOF持久化
        > appendonly yes
        > appendfsync everysec
        > EOF
        [root@redis201.oldboyedu.com ~]# 
        [root@redis201.oldboyedu.com ~]# cat /oldboyedu/softwares/redis16371/redis.conf 
        port 16371
        daemonize yes
        pidfile /oldboyedu/data/redis16371/redis.pid
        loglevel notice
        logfile /oldboyedu/data/redis16371/redis.log
        dbfilename dump.rdb
        dir /oldboyedu/data/redis16371
        bind 172.200.1.201 127.0.0.1
        requirepass oldboyedu
        masterauth oldboyedu
        # 配置RDB持久化策略
        save 900 1
        save 300 10
        save 60 10000
        # 配置AOF持久化
        appendonly yes
        appendfsync everysec
        [root@redis201.oldboyedu.com ~]# 

    (3)为"redis16372"实例创建配置文件
        [root@redis201.oldboyedu.com ~]# cat > /oldboyedu/softwares/redis16372/redis.conf <<EOF
        > port 16372
        > daemonize yes
        > pidfile /oldboyedu/data/redis16372/redis.pid
        > loglevel notice
        > logfile /oldboyedu/data/redis16372/redis.log
        > dbfilename dump.rdb
        > dir /oldboyedu/data/redis16372
        > bind 172.200.1.201 127.0.0.1
        > requirepass oldboyedu
        > masterauth oldboyedu
        > # 配置RDB持久化策略
        > save 900 1
        > save 300 10
        > save 60 10000
        > # 配置AOF持久化
        > appendonly yes
        > appendfsync everysec
        > EOF
        [root@redis201.oldboyedu.com ~]# 
        [root@redis201.oldboyedu.com ~]# cat /oldboyedu/softwares/redis16372/redis.conf 
        port 16372
        daemonize yes
        pidfile /oldboyedu/data/redis16372/redis.pid
        loglevel notice
        logfile /oldboyedu/data/redis16372/redis.log
        dbfilename dump.rdb
        dir /oldboyedu/data/redis16372
        bind 172.200.1.201 127.0.0.1
        requirepass oldboyedu
        masterauth oldboyedu
        # 配置RDB持久化策略
        save 900 1
        save 300 10
        save 60 10000
        # 配置AOF持久化
        appendonly yes
        appendfsync everysec
        [root@redis201.oldboyedu.com ~]# 

    温馨提示:
        (1)所有的requirepass建议设置为一致,这为我们"哨兵模式"做准备,很明显,"requirepass"表示配置当前实例的验证口令;
        (2)注意"masterauth"表示的含义是主库的验证口令;
        下面的模板你可以根据自己业务的实际需求进行改动即可~

cat > /oldboyedu/softwares/redis16372/redis.conf <<EOF
port 16372
daemonize yes
pidfile /oldboyedu/data/redis16372/redis.pid
loglevel notice
logfile /oldboyedu/data/redis16372/redis.log
dbfilename dump.rdb
dir /oldboyedu/data/redis16372
bind 172.200.1.201 127.0.0.1
requirepass oldboyedu
masterauth oldboyedu
# 配置RDB持久化策略
save 900 1
save 300 10
save 60 10000
# 配置AOF持久化
appendonly yes
appendfsync everysec
EOF

3.启动各个Redis实例

    (1)启动各个Redis实例
        [root@redis201.oldboyedu.com ~]# ss -ntl
        State       Recv-Q Send-Q                                                 Local Address:Port                                                                Peer Address:Port              
        LISTEN      0      128                                                                *:22                                                                             *:*                  
        LISTEN      0      128                                                             [::]:22                                                                          [::]:*                  
        [root@redis201.oldboyedu.com ~]# 
        [root@redis201.oldboyedu.com ~]# redis-server /oldboyedu/softwares/redis16370/redis.conf 
        [root@redis201.oldboyedu.com ~]# 
        [root@redis201.oldboyedu.com ~]# redis-server /oldboyedu/softwares/redis16371/redis.conf 
        [root@redis201.oldboyedu.com ~]# 
        [root@redis201.oldboyedu.com ~]# redis-server /oldboyedu/softwares/redis16372/redis.conf 
        [root@redis201.oldboyedu.com ~]# 
        [root@redis201.oldboyedu.com ~]# ss -ntl
        State       Recv-Q Send-Q                                                 Local Address:Port                                                                Peer Address:Port              
        LISTEN      0      128                                                        127.0.0.1:16370                                                                          *:*                  
        LISTEN      0      128                                                    172.200.1.201:16370                                                                          *:*                  
        LISTEN      0      128                                                        127.0.0.1:16371                                                                          *:*                  
        LISTEN      0      128                                                    172.200.1.201:16371                                                                          *:*                  
        LISTEN      0      128                                                        127.0.0.1:16372                                                                          *:*                  
        LISTEN      0      128                                                    172.200.1.201:16372                                                                          *:*                  
        LISTEN      0      128                                                                *:22                                                                             *:*                  
        LISTEN      0      128                                                             [::]:22                                                                          [::]:*                  
        [root@redis201.oldboyedu.com ~]# 

    (2)停止各个Redis实例运行,此步骤可跳过,因为我们暂时还不需要停止Redis,我们要用Redis实例做主从架构。
        [root@redis201.oldboyedu.com ~]# ss -ntl
        State       Recv-Q Send-Q                                                 Local Address:Port                                                                Peer Address:Port              
        LISTEN      0      128                                                        127.0.0.1:16370                                                                          *:*                  
        LISTEN      0      128                                                    172.200.1.201:16370                                                                          *:*                  
        LISTEN      0      128                                                        127.0.0.1:16371                                                                          *:*                  
        LISTEN      0      128                                                    172.200.1.201:16371                                                                          *:*                  
        LISTEN      0      128                                                        127.0.0.1:16372                                                                          *:*                  
        LISTEN      0      128                                                    172.200.1.201:16372                                                                          *:*                  
        LISTEN      0      128                                                                *:22                                                                             *:*                  
        LISTEN      0      128                                                             [::]:22                                                                          [::]:*                  
        [root@redis201.oldboyedu.com ~]# 
        [root@redis201.oldboyedu.com ~]# redis-cli -p 16370 -a oldboyedu shutdown
        [root@redis201.oldboyedu.com ~]# 
        [root@redis201.oldboyedu.com ~]# redis-cli -p 16371 -a oldboyedu shutdown
        [root@redis201.oldboyedu.com ~]# 
        [root@redis201.oldboyedu.com ~]# redis-cli -p 16372 -a oldboyedu shutdown
        [root@redis201.oldboyedu.com ~]# 
        [root@redis201.oldboyedu.com ~]# ss -ntl
        State       Recv-Q Send-Q                                                 Local Address:Port                                                                Peer Address:Port              
        LISTEN      0      128                                                                *:22                                                                             *:*                  
        LISTEN      0      128                                                             [::]:22                                                                          [::]:*                  
        [root@redis201.oldboyedu.com ~]# 

4.开启Redis的主从

    实验说明:
        以"redis16370"实例为主库,以"redis16371"实例和"redis16372"实例为从库。

    从库实例开启主从:
        [root@redis201.oldboyedu.com ~]# redis-cli -p 16371 -a oldboyedu SLAVEOF 172.200.1.201 16370
        OK
        [root@redis201.oldboyedu.com ~]# 
        [root@redis201.oldboyedu.com ~]# redis-cli -p 16372 -a oldboyedu SLAVEOF 172.200.1.201 16370
        OK
        [root@redis201.oldboyedu.com ~]# 

5.主库实例查看主从信息

[root@redis201.oldboyedu.com ~]# redis-cli -p 16370 -a oldboyedu INFO REPLICATION
# Replication
role:master
connected_slaves:2
slave0:ip=172.200.1.201,port=16371,state=online,offset=127,lag=1
slave1:ip=172.200.1.201,port=16372,state=online,offset=127,lag=1
master_repl_offset:127
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:126
[root@redis201.oldboyedu.com ~]# 

6.从库实例查看主从信息

    (1)在"redis16371"实例中查看主从状态信息:
        [root@redis201.oldboyedu.com ~]# redis-cli -p 16371 -a oldboyedu INFO REPLICATION
        # Replication
        role:slave
        master_host:172.200.1.201
        master_port:16370
        master_link_status:up
        master_last_io_seconds_ago:1
        master_sync_in_progress:0
        slave_repl_offset:379
        slave_priority:100
        slave_read_only:1
        connected_slaves:0
        master_repl_offset:0
        repl_backlog_active:0
        repl_backlog_size:1048576
        repl_backlog_first_byte_offset:0
        repl_backlog_histlen:0
        [root@redis201.oldboyedu.com ~]# 

    (2)在"redis16372"实例中查看主从状态信息:
        [root@redis201.oldboyedu.com ~]# redis-cli -p 16372 -a oldboyedu INFO REPLICATION
        # Replication
        role:slave
        master_host:172.200.1.201
        master_port:16370
        master_link_status:up
        master_last_io_seconds_ago:4
        master_sync_in_progress:0
        slave_repl_offset:379
        slave_priority:100
        slave_read_only:1
        connected_slaves:0
        master_repl_offset:0
        repl_backlog_active:0
        repl_backlog_size:1048576
        repl_backlog_first_byte_offset:0
        repl_backlog_histlen:0
        [root@redis201.oldboyedu.com ~]# 

7.验证主从配置是否生效

    (1)在"redis16370"实例主库的11号数据库创建测试数据
        [root@redis201.oldboyedu.com ~]# redis-cli -p 16370 -a oldboyedu -n 11
        127.0.0.1:16370[11]> KEYS *
        (empty list or set)
        127.0.0.1:16370[11]> 
        127.0.0.1:16370[11]> SET name JasonYin
        OK
        127.0.0.1:16370[11]> 
        127.0.0.1:16370[11]> SET age 18
        OK
        127.0.0.1:16370[11]> 
        127.0.0.1:16370[11]> KEYS *
        1) "age"
        2) "name"
        127.0.0.1:16370[11]> 
        127.0.0.1:16370[11]> QUIT
        [root@redis201.oldboyedu.com ~]# 

    (2)在"redis16371"实例从库的11号数据库查看是否同步主库的11号数据库
        [root@redis201.oldboyedu.com ~]# redis-cli -p 16371 -a oldboyedu -n 11
        127.0.0.1:16371[11]> KEYS *
        1) "age"
        2) "name"
        127.0.0.1:16371[11]> 
        127.0.0.1:16371[11]> GET name
        "JasonYin"
        127.0.0.1:16371[11]> 
        127.0.0.1:16371[11]> GET age
        "18"
        127.0.0.1:16371[11]> 
        127.0.0.1:16371[11]> QUIT
        [root@redis201.oldboyedu.com ~]# 

    (2)在"redis16372"实例从库的11号数据库查看是否同步主库的11号数据库
        [root@redis201.oldboyedu.com ~]# redis-cli -p 16372 -a oldboyedu -n 11
        127.0.0.1:16372[11]> KEYS *
        1) "name"
        2) "age"
        127.0.0.1:16372[11]> 
        127.0.0.1:16372[11]> GET name
        "JasonYin"
        127.0.0.1:16372[11]> 
        127.0.0.1:16372[11]> GET age
        "18"
        127.0.0.1:16372[11]> 
        127.0.0.1:16372[11]> QUIT
        [root@redis201.oldboyedu.com ~]# 

8.解除"redis16372"实例的主从关系

[root@redis201.oldboyedu.com ~]# redis-cli -p 16372 -a oldboyedu info replication
# Replication
role:slave
master_host:172.200.1.201
master_port:16370
master_link_status:up
master_last_io_seconds_ago:8
master_sync_in_progress:0
slave_repl_offset:8240
slave_priority:100
slave_read_only:1
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
[root@redis201.oldboyedu.com ~]# 
[root@redis201.oldboyedu.com ~]# redis-cli -p 16370 -a oldboyedu info replication
# Replication
role:master
connected_slaves:2
slave0:ip=172.200.1.201,port=16371,state=online,offset=8310,lag=1
slave1:ip=172.200.1.201,port=16372,state=online,offset=8310,lag=0
master_repl_offset:8310
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:8309
[root@redis201.oldboyedu.com ~]# 
[root@redis201.oldboyedu.com ~]# redis-cli -p 16372 -a oldboyedu SLAVEOF NO ONE  # 解除"redis16372"实例的主从关系
OK
[root@redis201.oldboyedu.com ~]# 
[root@redis201.oldboyedu.com ~]# 
[root@redis201.oldboyedu.com ~]# redis-cli -p 16370 -a oldboyedu info replication
# Replication
role:master
connected_slaves:1
slave0:ip=172.200.1.201,port=16371,state=online,offset=8310,lag=0
master_repl_offset:8310
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:8309
[root@redis201.oldboyedu.com ~]# 
[root@redis201.oldboyedu.com ~]# redis-cli -p 16372 -a oldboyedu info replication
# Replication
role:master
connected_slaves:0
master_repl_offset:8310
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
[root@redis201.oldboyedu.com ~]# 

四.跨节点部署Redis集群实战案例

(0)主从架构设计
    主库为:
        10.0.0.108
    从库:
        10.0.0.106
        10.0.0.107

(1)10.0.0.106的配置
install -d /oldboyedu/data/redis
cat > /oldboyedu/softwares/redis/conf/redis.conf <<EOF
port 8106
daemonize yes
pidfile /oldboyedu/data/redis/redis.pid
loglevel notice
logfile /oldboyedu/data/redis/redis.log
dbfilename oldboyedu_linux.rdb
dir /oldboyedu/data/redis/
bind 10.0.0.106
requirepass oldboyedu
masterauth oldboyedu
# 配置RDB持久化策略
save 900 1
save 300 10
save 60 10000
EOF

redis-server /oldboyedu/softwares/redis/conf/redis.conf

(2)10.0.0.107的配置
install -d /oldboyedu/data/redis
cat > /oldboyedu/softwares/redis/conf/redis.conf <<EOF
port 8107
daemonize yes
pidfile /oldboyedu/data/redis/redis.pid
loglevel notice
logfile /oldboyedu/data/redis/redis.log
dbfilename oldboyedu_linux.rdb
dir /oldboyedu/data/redis/
bind 10.0.0.107
requirepass oldboyedu
masterauth oldboyedu
# 配置RDB持久化策略
save 900 1
save 300 10
save 60 10000
EOF

redis-server /oldboyedu/softwares/redis/conf/redis.conf

(3)10.0.0.108的配置
install -d /oldboyedu/data/redis
cat > /oldboyedu/softwares/redis/conf/redis.conf <<EOF
port 8108
daemonize yes
pidfile /oldboyedu/data/redis/redis.pid
loglevel notice
logfile /oldboyedu/data/redis/redis.log
dbfilename oldboyedu_linux.rdb
dir /oldboyedu/data/redis/
bind 10.0.0.108
requirepass oldboyedu
masterauth oldboyedu
# 配置RDB持久化策略
save 900 1
save 300 10
save 60 10000
EOF

redis-server /oldboyedu/softwares/redis/conf/redis.conf

(4)从库开启主从
    10.0.0.106:
        redis-cli -p 8106 -h 10.0.0.106 -a oldboyedu SLAVEOF 10.0.0.108 8108
    10.0.0.107:
        redis-cli -p 8107 -h 10.0.0.107 -a oldboyedu SLAVEOF 10.0.0.108 8108
谨此笔记,记录过往。凭君阅览,如能收益,莫大奢望。
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇