Redis学习(六):主从复制,发布订阅和实际可能遇到缓存失效的情况

news2025/7/25 10:19:12

Redis发布订阅

Redis发布订阅(Public/Subscribe)是一种消息通信模式:发送者发送消息,订阅者接收消息。

Redis客户端可以订阅任意数量的频道。

image-20230307103052963

这张图里有三个角色:

  1. 消息发送者
  2. 频道(消息队列)
  3. 消息订阅者

image-20230307103549580

测试

一个客户端作为订阅者,输入命令后会进入等待读的模式

image-20230307104046827

另外一个客户端可以在频道上发布信息

image-20230307104215718

消息发布成功后可以在订阅者这里看到发送的信息

image-20230307104236737

使用场景

  • 实时消息系统
  • 实时聊天
  • 订阅,关注系统

稍微复杂的场景使用消息中间件MQ去做。

Redis主从复制

概念

主从复制,是将一台Redis服务器的数据,复制到其他的Redis服务器。前者称为主节点(master/leader),后者称为从节点(slave/follwer);数据的复制是单向的,只能由主节点到从节点。Master以写为主,Slave以读为主。

默认情况下,每台Redis服务器都是主节点;一个主节点可以有任意个从节点,但是一个从节点只能有一个主节点。

主从复制的作用主要包括:

  1. 数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式
  2. 故障恢复:当主节点出现问题时,可以由从节点提供服务,实现快速地故障恢复;实际上是一种服务的冗余。
  3. 负载均衡:在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务(写数据时连接的是主节点,读数据的时候连接的是从节点),分担服务器负载;尤其是写少读多的场景下,通过多个从节点分担读负载,可以提高Redis服务器的并发量。
  4. 高可用的基石:除了上述作用以外,主从复制还是哨兵和集群能够实施的基础。

一般来说,不能只使用一台Redis

  1. 从结构上,单个Redis服务器惠州发生单点故障,并且一台服务器需要处理所有的请求负载,压力较大
  2. 从容量上,单个Redis服务器内存容量有限,一般单台Redis最大使用内存不应该超过20G

环境配置

使用多个配置文件开启多个服务器,模拟集群环境。

使用多个配置文件的时候需要修改这些东西

  • 端口号
  • pid文件的名字
  • 日志的名字
  • dump文件的名字

启动之后可以看到有多个后台进程
image-20230307143638883

可以使用info命令查看当前客户端连接的结点是主节点还是从节点
image-20230307112639180

localhost:6379> info replication
# Replication
role:master    # 角色 master
connected_slaves:0  # 从机数量
master_failover_state:no-failover
master_replid:5a317ebb25d39a747f03df02a3128506e02b7997
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0

主从设置

由于我们启动了三个服务,所以我们按一主二从的方式来配置集群;一般情况下只用配置从机就好了。
我们用6379当做主机(6380和6381)当做从机。

使用 SLAVEOF 命令来配置主机。
下面是一个从机配置后的效果

127.0.0.1:6380> SLAVEOF localhost 6379
OK
127.0.0.1:6380> info replication
# Replication
role:slave
master_host:localhost
master_port:6379
master_link_status:up
master_last_io_seconds_ago:5
master_sync_in_progress:0
slave_read_repl_offset:14
slave_repl_offset:14
slave_priority:100
slave_read_only:1
replica_announced:1
connected_slaves:0
master_failover_state:no-failover
master_replid:63ce04839a97c637ed61bfcfb982056de47db760
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:14
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:14
127.0.0.1:6380> 

另一台也使用上面的命令配置,然后在主机上查看info replication

localhost:6379> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=::1,port=6380,state=online,offset=280,lag=1
slave1:ip=::1,port=6381,state=online,offset=280,lag=0
master_failover_state:no-failover
master_replid:63ce04839a97c637ed61bfcfb982056de47db760
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:280
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:280
localhost:6379> 

可以看到主机上正确显示了两个从机。
真实的主从配置是在配置文件里修改的,这样命令只是暂时更改的
image-20230307144912269

细节

主机可以写,从机不能写,主机中的所有信息和数据,都会自动被从机保存。在主机上设置的值可以在从机上读到,从机上不能设置值

image-20230307145208595

测试之后可以发现:主机断开连接,从机依旧可以正常读取,且主机重新上线后,从机依然可以同步主机写的内容。从机断开连接重新连接后,也可以同步自己下线时缺失的信息。

复制原理

Slave启动成功连接到master后会发送一个sync同步命令
Master接收到命令,启动后台的存盘进程,同时收集所有接收到的用于修改数据集的命令,在后台进程执行完毕之后,master将传送整个数据文件到slave,完成一次同步。

全量复制:Slave在接受到数据文件后,将其存盘并加载到内存中

增量复制:Master继续将新的修改命令一次传给slave,完成同步

但是只要重新连接master,一次全量复制将被自动执行。

特殊结构

一个从节点还可以连接其他的从节点,形成一个三层的结构,但是中间的结点依然是不能写入的从节点。

image-20230307151636217

这个时候依然可以完成主从复制。

当主节点宕机之后,80主机可以执行SLAVEOF no one命令,将他自己变成主机。

哨兵模式(自动配置主节点的模式)

概述

主从切换技术的方法是:当主服务器宕机后,需要手动吧一台从服务器切换为主服务器,这就需要人工干预,费时费力,还会导致一段时间内服务不可用。这不是一种推荐的方式,更多时候,我们优先考虑哨兵模式。Redis从2.8开始正式提供了Sentinel(哨兵)架构来解决这个问题。

他能够后台监控主机是否故障,如果故障之后,哨兵会根据投票数自动将从库转换为主库。

哨兵模式是一种特殊的模式,首先Redis提供了哨兵的命令,哨兵是一个独立的进程,作为进程,他会独立运行。其原理就是哨兵通过发送命令,等待Redis服务器响应(如果没有响应,就说明某个服务器出故障了),从而监控多个Redis实例

image-20230307152846474

这里的哨兵有两个作用

  • 通过发送命令,让Redis服务器返回其运行状态
  • 当哨兵检测到master宕机,会自动将slave切换成master,然后通过发布订阅模式通知其他的从服务器,修改配置文件,让他们切换主机。

然而哨兵也可能宕机,所以我们使用多个哨兵进行监控,各个哨兵之间也会监控,这样就形成了多哨兵模式。

image-20230307153049174

image-20230307153214784

测试

目前状态是前面配置的一主二从。

  1. 配置哨兵配置文件 sentinel.conf

    # sentinel monitor 被监控的名称 host 端口号 
    sentinel monitor myredis 127.0.0.1 6379 1
    

    最后的1代表同意主节点不可用的sentinel的节点数量。

  2. 启动哨兵

    和启动服务器的方法一样,也是指定配置文件启动
    image-20230307154609390

    启动后可以看到哨兵这里显示了监视的主机和从机

    image-20230307154718990

    模拟一下主机宕机,等待一会可以发现哨兵进程这里进行了主机的转换

    image-20230307165849483

    再把旧主节点上线,可以看到旧主节点当成了新主节点的从机。

优点:

  1. 哨兵集群基于主从模式,所以它具有所有主从配置的优点
  2. 主从可以切换,故障可以转移,系统的可用性更好
  3. 哨兵模式就是主从模式的升级,手动到自动

缺点:

  1. 不好在线扩容,集群容量一旦达到上线,在线扩容十分麻烦
  2. 实现哨兵模式的配置较为复杂
# Example sentinel.conf

# *** IMPORTANT ***
# 绑定IP地址
# bind 127.0.0.1 192.168.1.1
# 保护模式(是否禁止外部链接,除绑定的ip地址外)
# protected-mode no

# port <sentinel-port>
# 此Sentinel实例运行的端口
port 26379

# 默认情况下,Redis Sentinel不作为守护程序运行。 如果需要,可以设置为 yes。
daemonize no

# 启用守护进程运行后,Redis将在/var/run/redis-sentinel.pid中写入一个pid文件
pidfile /var/run/redis-sentinel.pid

# 指定日志文件名。 如果值为空,将强制Sentinel日志标准输出。守护进程下,如果使用标准输出进行日志记录,则日志将发送到/dev/null
logfile ""

# sentinel announce-ip <ip>
# sentinel announce-port <port>
#
# 上述两个配置指令在环境中非常有用,因为NAT可以通过非本地地址从外部访问Sentinel。
#
# 当提供announce-ip时,Sentinel将在通信中声明指定的IP地址,而不是像通常那样自动检测本地地址。
#
# 类似地,当提供announce-port 有效且非零时,Sentinel将宣布指定的TCP端口。
#
# 这两个选项不需要一起使用,如果只提供announce-ip,Sentinel将宣告指定的IP和“port”选项指定的服务器端口。
# 如果仅提供announce-port,Sentinel将通告自动检测到的本地IP和指定端口。
#
# Example:
#
# sentinel announce-ip 1.2.3.4

# dir <working-directory>
# 每个长时间运行的进程都应该有一个明确定义的工作目录。对于Redis Sentinel来说,/tmp就是自己的工作目录。
dir /tmp

# sentinel monitor <master-name> <ip> <redis-port> <quorum>
#
# 告诉Sentinel监听指定主节点,并且只有在至少<quorum>哨兵达成一致的情况下才会判断它 O_DOWN 状态。
#
#
# 副本是自动发现的,因此您无需指定副本。
# Sentinel本身将重写此配置文件,使用其他配置选项添加副本。另请注意,当副本升级为主副本时,将重写配置文件。
#
# 注意:主节点(master)名称不能包含特殊字符或空格。
# 有效字符可以是 A-z 0-9 和这三个字符 ".-_".
sentinel monitor mymaster 127.0.0.1 6379 2

# 如果redis配置了密码,那这里必须配置认证,否则不能自动切换
# Example:
#
# sentinel auth-pass mymaster MySUPER--secret-0123passw0rd

# sentinel down-after-milliseconds <master-name> <milliseconds>
#
# 主节点或副本在指定时间内没有回复PING,便认为该节点为主观下线 S_DOWN 状态。
#
# 默认是30秒
sentinel down-after-milliseconds mymaster 30000

# sentinel parallel-syncs <master-name> <numreplicas>
#
# 在故障转移期间,多少个副本节点进行数据同步
sentinel parallel-syncs mymaster 1

# sentinel failover-timeout <master-name> <milliseconds>
#
# 指定故障转移超时(以毫秒为单位)。 它以多种方式使用:
#
# - 在先前的故障转移之后重新启动故障转移所需的时间已由给定的Sentinel针对同一主服务器尝试,是故障转移超时的两倍。
#
# - 当一个slave从一个错误的master那里同步数据开始计算时间。直到slave被纠正为向正确的master那里同步数据时。
#
# - 取消已在进行但未生成任何配置更改的故障转移所需的时间
#
# - 当进行failover时,配置所有slaves指向新的master所需的最大时间。
#   即使过了这个超时,slaves依然会被正确配置为指向master。
#
# 默认3分钟
sentinel failover-timeout mymaster 180000

# 脚本执行
#
# sentinel notification-script和sentinel reconfig-script用于配置调用的脚本,以通知系统管理员或在故障转移后重新配置客户端。
# 脚本使用以下规则执行以进行错误处理:
#
# 如果脚本以“1”退出,则稍后重试执行(最多重试次数为当前设置的10次)。
#
# 如果脚本以“2”(或更高的值)退出,则不会重试执行。
#
# 如果脚本因为收到信号而终止,则行为与退出代码1相同。
#
# 脚本的最长运行时间为60秒。 达到此限制后,脚本将以SIGKILL终止,并重试执行。

# 通知脚本
#
# sentinel notification-script <master-name> <script-path>
#
# 为警告级别生成的任何Sentinel事件调用指定的通知脚本(例如-sdown,-odown等)。
# 此脚本应通过电子邮件,SMS或任何其他消息传递系统通知系统管理员 监控的Redis系统出了问题。
#
# 使用两个参数调用脚本:第一个是事件类型,第二个是事件描述。
#
# 该脚本必须存在且可执行,以便在提供此选项时启动sentinel。
#
# 举例:
#
# sentinel notification-script mymaster /var/redis/notify.sh

# 客户重新配置脚本
#
# sentinel client-reconfig-script <master-name> <script-path>
#
# 当主服务器因故障转移而变更时,可以调用脚本执行特定于应用程序的任务,以通知客户端,配置已更改且主服务器地址已经变更。
#
# 以下参数将传递给脚本:
#
# <master-name> <role> <state> <from-ip> <from-port> <to-ip> <to-port>
#
# <state> 目前始终是故障转移 "failover"
# <role> 是 "leader" 或 "observer"
#
# 参数 from-ip, from-port, to-ip, to-port 用于传递主服务器的旧地址和所选副本的新地址。
#
# 举例:
#
# sentinel client-reconfig-script mymaster /var/redis/reconfig.sh

# 安全
# 避免脚本重置,默认值yes
# 默认情况下,SENTINEL SET将无法在运行时更改notification-script和client-reconfig-script。
# 这避免了一个简单的安全问题,客户端可以将脚本设置为任何内容并触发故障转移以便执行程序。
sentinel deny-scripts-reconfig yes

# REDIS命令重命名
#
#
# 在这种情况下,可以告诉Sentinel使用不同的命令名称而不是正常的命令名称。
# 例如,如果主“mymaster”和相关副本的“CONFIG”全部重命名为“GUESSME”,我可以使用:
#
# SENTINEL rename-command mymaster CONFIG GUESSME
#
# 设置此类配置后,每次Sentinel使用CONFIG时,它将使用GUESSME。 请注意,实际上不需要尊重命令案例,因此在上面的示例中写“config guessme”是相同的。
#
# SENTINEL SET也可用于在运行时执行此配置。
#
# 为了将命令设置回其原始名称(撤消重命名),可以将命令重命名为它自身:
#
# SENTINEL rename-command mymaster CONFIG CONFIG

缓存穿透、缓存击穿和雪崩

这都是服务的高可用问题。

缓存穿透

概念

缓存穿透是指恶意用户故意访问缓存中不存在,但是数据库中也不存在的数据,这会导致请求全部打到数据库上,造成数据库的短时间内的压力剧增。

布隆过滤器

image-20230307174035826

缓存空对象

image-20230307174129707

这个方法存在两个文分体

  1. 空对象会占用额外的空间,因为空对象也会占用键
  2. 及时对空值设置了过期时间,还是会在缓存层和存储层的数据会有一段时间不一致,这对于需要保持一致性的业务有影响

缓存击穿

概念

是指一个key非常热点,在不停承受这大并发,当这个key失效的瞬间,持续的大并发就穿透了缓存,直接请求数据库。

当某个key在过期的瞬间,有大量的请求并发访问,这类数据一般是热点数据,由于缓存过期,会同时访问数据库来查询最新数据,并且回写缓存,会导致数据库瞬间压力过大。

解决方案

  • 设置热点数据永不过期

    从缓存层面上看,没有设置过期时间,所以不会出现热点key过期后产生的问题

  • 加互斥锁

    分布式锁:保证对于每个key同时只有一个线程去查询后端服务,其他线程没有获得分布式锁的权限,因此只需要等待即可。这种方式将高并发的压力转移到了分布式锁,因此对分布式锁的考验很大。

缓存雪崩

概念

指在某一段时间,缓存集中过期失效,或者缓存服务器宕机。

image-20230307175335269

解决方案

  • redis高可用

    多增设几台redis,这样一台挂掉之后其他的还可以继续工作,其实就是搭建集群。(异地多活)

  • 限流降级

    在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和写缓存,其他线程等待。

  • 数据预热

    在正式部署之前,先把可能访问的数据预先访问一遍,这样使这些数据加载到缓存中。在即将发生大并发访问前手动触发加载缓存不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/394812.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

AIGC时代,大模型微调如何发挥最大作用?

人工智能的快速发展推动了大模型的广泛应用&#xff0c;它们在语言、视觉、语音等领域的应用效果已经越来越好。但是&#xff0c;训练一个大模型需要巨大的计算资源和时间&#xff0c;为了减少这种资源的浪费&#xff0c;微调已经成为一种流行的技术。微调是指在预训练模型的基…

2023年3月全国DAMA-CDGA/CDGP数据管理认证火热报名中...

弘博创新是DAMA中国授权的数据治理人才培养基地&#xff0c;贴合市场需求定制教学体系&#xff0c;采用行业资深名师授课&#xff0c;理论与实践案例相结合&#xff0c;快速全面提升个人/企业数据治理专业知识与实践经验&#xff0c;通过考试还能获得数据专业领域证书。 DAMA认…

【iOS】—— 浅看block源码

block 文章目录block如何通过终端clang生成源码cpp文件block实质截获自动变量全局变量和静态变量的截获__block说明符iOS开发“强弱共舞”——weak和strong配套使用解决block循环引用问题如何通过终端clang生成源码cpp文件 之前在学习block中学习的比较浅&#xff0c;只看了oc…

sentinel源码入门

sentinel是一个流量治理组件&#xff0c;主要用来做降级、熔断和限流&#xff0c;以及监控等&#xff0c;sentinel的使用相对来说比较简单&#xff0c;这篇博客主要介绍sentinel的源码 入口 在使用sentinel的时候&#xff0c;我们需要引入sentinel的相关jar包&#xff0c;然后…

如何使用码匠连接 ClickHouse

目录 在码匠中集成 ClickHouse 在码匠中使用 ClickHouse 关于码匠 ClickHouse 数据源是一种列式数据库管理系统&#xff0c;由俄罗斯 Yandex 公司开发和维护。它专注于高性能、高并发、高可扩展性和低延迟的数据处理&#xff0c;特别是在海量数据的 OLAP&#xff08;联机分析…

性能分析利器:火焰图

什么是火焰图 火焰图&#xff08;FlameGraph&#xff09;是是由 Linux 性能优化大师 Brendan Gregg 发明的。通过 perf 等工具分析得到结果&#xff0c;看起来就像是火焰&#xff0c;这也是它的名字的由来。火焰图以一个全局的视野来看待时间分布&#xff0c;它从底部往顶部&am…

Dockerfile部署SpringBoot项目

Dockerfile部署SpringBoot项目 文章目录 利用Dockerfile部署SpringBoot项目 1、创建一个SpringBooot项目并且打成jar包2、在Linux中创建一个文件夹&#xff0c;来做docker测试3、将jar包上传到Linux中4、编写Dockerfile文件5、制作镜像6、启动容器7、查看容器启动日志8、访问接…

高效能自动化港口数字化码头智慧港航,中国人工智能企业CIMCAI世界港航人工智能领军者,成熟港口码头人工智能产品中国人工智能企业

打造高效能自动化港口数字化码头智慧港航&#xff0c;中国人工智能企业CIMCAI中集飞瞳世界港航人工智能领军者&#xff0c;成熟港口码头人工智能产品全球顶尖AI科技CIMCAI成熟AI产品全球前三船公司及港口落地&#xff0c;包括全球港口/堆场智能闸口验箱&#xff0c;全球港口岸边…

Vulnhub系列:Raven 1

该篇为Vulnhub系列靶机渗透&#xff0c;本次靶机存在4个flag。下面开始我们今天的渗透之旅。Raven靶机有很多种思路&#xff0c;我将对其进行一一整理。首先进行信息收集&#xff0c;利用arp-scan和nmap&#xff0c;进行靶机的ip及端口扫描发现了22、80、111端口。下面访问80端…

【LeetCode】剑指 Offer 23. 链表中环的入口节点 p139 -- Java Version

题目链接&#xff1a;https://leetcode.cn/problems/c32eOV/ 1. 题目介绍&#xff08;23. 链表中环的入口节点&#xff09; 给定一个链表&#xff0c;返回链表开始入环的第一个节点。 从链表的头节点开始沿着 next 指针进入环的第一个节点为环的入口节点。如果链表无环&#x…

怎么清空回收站?3分钟解决!

真实案例&#xff1a;回收站清空不了怎么办&#xff1f;怎样清空回收站里的文件&#xff1f; “各位大神&#xff0c;怎么恢复回收站里清空的文件&#xff1f;我按照百度上的方法&#xff0c;还是不行。” 当你在电脑上删除文件时&#xff0c;它们通常会被移到回收站&#xf…

mpi4py 运行过程中出现Read -1, expected xxx, errno = 1 解决方案

目录 问题描述 代码1&#xff08;串行&#xff09; 代码2&#xff08;并行&#xff09; 代码2执行时所用指令 错误信息 解决方案 解决方案1 解决方案2 问题描述 今天正在学习使用mpi4py&#xff0c;在对比运行以下2个代码时疯狂报错&#xff1a; 代码1&#xff08;串…

HTML 脚本

HTML 脚本 JavaScript 是可插入 HTML 页面的编程代码。 JavaScript 使 HTML 页面具有更强的动态和交互性。 JavaScript 插入 HTML 页面后&#xff0c;可由所有的现代浏览器执行。 在线实例 插入一段脚本 如何将脚本插入 HTML 文档。 使用 <noscript> 标签 如何应对不…

非接触式流量监测设备——雷达流速仪

一、设备概述 雷达流速仪是一款非接触且可连续测量流速、水位、流量的一体式流量监测设备。它采用雷达平面微波技术&#xff0c;通过非接触方式测量水体的流速和水位。根据内置的软件算法&#xff0c;计算并输出实时断面流量及累计流量&#xff1b;可用于泵站、河道、灌渠、地…

扬帆优配|三大油气巨头都嗨了,龙头总市值盘中破万亿

近期组织盯上哪些股&#xff1f; 3月7日早盘&#xff0c;周期板块大幅上涨。石油板块涨超4%遥遥领先&#xff0c;海越能源涨停。油气巨头我国石油盘中涨近6%&#xff0c;总市值一度突破万亿元。我国石化盘中涨幅到达6.86%&#xff0c;股价创四年来新高。我国海油盘中涨停&#…

Rocketmq技术详解

Rocketmq技术详解 运维部署 docker-compose.yml version: 3.5 services:rmqnamesrv:image: foxiswho/rocketmq:servercontainer_name: rmqnamesrvports:- 9876:9876volumes:- ./logs:/opt/logs- ./store:/opt/storenetworks:rmq:aliases:- rmqnamesrvrmqbroker:image: foxisw…

后疫情时代,EIoT助力实体零售ESG战略落地

多点智能物联总经理刘汉彻 2023一开年&#xff0c;烟火气回归&#xff0c;各行各业都在摩拳擦掌&#xff0c;准备在后疫情元年“大干一场”。对企业而言&#xff0c;“降本增效”已成为跨行业的共同认知&#xff0c;实体零售也给自身的发展标定了方向&#xff1a;“彻底回归商…

CSS清楚浮动

先看看关于浮动的一些性质 浮动使元素脱离文档流 浮动元素可以设置宽高&#xff0c;在CSS中&#xff0c;任何元素都可以浮动&#xff0c;浮动元素会生成一个块级框&#xff0c;而不论其本身是何种元素。 如果没有给浮动元素指定高度&#xff0c;&#xff0c;那么它会以内容的…

JAVA SE: IO流

一、Java流式输入输出原理Java对于输入输出是以流(Stream)的方式进行的&#xff0c;JDK提供各种各样的“流”类&#xff0c;以获取不同类型的数据。可以理解为将管道插入到文件中&#xff0c;然后从管道获取数据。这个管道外边还可以套管道&#xff0c;外边的管道对数据进行处理…

Transwarp KunDB 备份恢复工具安装和备份工作自动化

备份恢复工具安装安装包# KunDR压缩包 KUNTOOL-Image-Registry-3.0.0-X86_64-final.tar.gzservice_client └── kuntools-3.0.0-final├── kundr-3.0.tar.gz└── kuntools-3.0.tar.gzkundr-3.0.tar.gz ├── bin │ ├── kunkun.sh │ ├── kuntools │ └──…