
架构
文章平均质量分 86
六月·飞雪
这个作者很懒,什么都没留下…
展开
-
开源支付系统
Jeepay是一套适合互联网企业使用的开源支付系统,支持多渠道服务商和普通商户模式。已对接微信支付支付宝云闪付官方接口,支持聚合码支付。Jeepay使用和开发,集成实现权限管理功能,是一套非常实用的web开发框架。原创 2023-08-27 20:35:24 · 486 阅读 · 0 评论 -
基于 ThreadLocal 实现一个上下文管理组件
在工作中,我们经常需要维护一些上下文,这样可以避免在方法调用过程中传入过多的参数,需要查询/修改一些数据的时候,直接在当前上下文中操作就行了。举个具体点的例子:当web服务器收到一个请求时,需要解析当前登录态的用户,在后续的业务执行流程中都需要这个用户名。如果只需要维护一个上下文状态数据还比较好处理,可以通过方法传参的形式,执行每个业务方法的时候都通过添加一个表示用户名方法参数传递进去,但是如果需要维护上下文状态数据比较多的话,这个方式就不太优雅了。一个可行的方案是通过。原创 2023-08-27 20:23:19 · 336 阅读 · 0 评论 -
JVM 锁优化和逃逸分析详解
这里的答案是不会,x + y + z 操作的优化「经过逃逸分析」过后,他的动态作用域被限制在了 concatStr方法内,就是说当前实际执行的 StringBuilder 的操作在 concatStr 方法内部,「其他的外部线程无法访问」到,所以这里「虽然有锁,但是可以被安全的消除掉。原则上,我们在写代码的时候,总是推荐将同步块的作用范围限制得尽可能的小--只在共享数据的实际操作作用域中才进行同步,这样也是为了使得需要同步的操作尽可能的变少,即使存在锁的竞争,等待的锁的线程也能很快的获取到锁。原创 2023-08-27 20:08:47 · 126 阅读 · 0 评论 -
Redis 客户端
我们看了这三种方式,这里仅仅是做了个入门,每个里面都有很多细节的地方需要去研究和使用,整体的感觉是要想使用的简单,那么存储在Redis中的数据就要量少,量大后,就需要自己来定制了,那基本上要用RedisTemplate来做一些工作。原创 2023-08-27 20:04:08 · 119 阅读 · 0 评论 -
Spring 事务失效的十种常见场景
Spring针对Java Transaction API (JTA)、JDBC、Hibernate和Java Persistence API(JPA)等事务 API,实现了一致的编程模型,而Spring的声明式事务功能更是提供了极其方便的事务配置方式,配合Spring Boot的自动配置,大多数Spring Boot项目只需要在方法上标记注解,即可一键开启方法的事务性配置。原创 2023-08-27 20:02:16 · 145 阅读 · 0 评论 -
MySQL 中的 distinct 和 group by 哪个效率更高
DISTINCT和GROUP BY都是可以使用索引进行扫描搜索的。例如以下两条sql(只单单看表格最后extra的内容),我们对这两条sql进行分析,可以看到,在extra中,这两条sql都使用了紧凑索引扫描。所以,在一般情况下,对于相同语义的DISTINCT和GROUP BY语句,我们可以对其使用相同的索引优化手段来进行优化。但对于GROUP BY来说,在MYSQL8.0之前,GROUP Y默认会依据字段进行隐式排序。可以看到,下面这条sql语句在使用了临时表的同时,还进行了filesort。原创 2023-08-27 19:53:00 · 282 阅读 · 0 评论 -
Redis 性能更强的数据库KeyDB
KeyDB是Redis的高性能分支,专注于多线程,内存效率和高吞吐量。除了多线程之外,KeyDB还具有仅在Redis Enterprise中可用的功能,例如Active Replication,FLASH存储支持以及一些根本不可用的功能,例如直接备份到AWS S3。KeyDB与Redis协议,模块和脚本保持完全兼容性。这包括脚本和事务的原子性保证。由于KeyDB与Redis开发保持同步,因此KeyDB是Redis功能的超集,从而使KeyDB取代了现有Redis部署。原创 2023-08-27 19:50:37 · 558 阅读 · 1 评论 -
分布式十二问
分布式事务是相对本地事务而言的,对于本地事务,利用数据库本身的事务机制,就可以保证事务的ACID特性。而在分布式环境下,会涉及到多个数据库。多数据库分布式事务其实就是将对同一库事务的概念扩大到了对多个库的事务。目的是为了保证分布式系统中的数据一致性。分布式事务处理的关键是:需要记录事务在任何节点所做的所有动作;事务进行的所有操作要么全部提交,要么全部回滚。什么是幂等性?同一个接口,多次发出同一个请求,请求的结果是一致的。简单说,就是多次调用如一次。什么是幂等性问题?原创 2023-08-27 19:42:20 · 131 阅读 · 0 评论 -
顶级Java类库
下面是收集的一些有用的第三方库,Java 开发人员可以在他们的应用程序中使用它们来完成很多有用的任务。从 JDK 8 开始,没有理由使用 Joda,因为您可以在 JDK 8 的新日期和时间 API中获得所有这些功能,但是如果您使用的是较旧的 Java 版本,那么 JodaTime 是一个值得学习的库。优秀且经验丰富的 Java 开发人员的特点之一是对 API 的广泛了解,包括 JDK 和第三方库。在 Java 8 之前,JDK 的数据和时间库有很多缺陷,因为它们不是线程安全的、不可变的和容易出错的。原创 2023-08-27 19:15:47 · 107 阅读 · 0 评论 -
ES+Redis+MySQL
但在实际使用的过程中,申请了该账号的同事,可能异动到其他部门了,此时他可能也会调用会员系统,为了省事,他不会再次申请会员账号,而是直接沿用以前的账号过来调用,这导致我们无法判断一个会员账号的具体使用场景是什么,也就无法实施更精细的流控和降级策略。所以,我们采取的策略是,在试运行期间,主写 SqlServer,然后通过线程池异步写 MySQL,如果写失败了,重试三次,如果依然失败,则记日志,然后人工排查原因,解决后,继续双写,直到运行一段时间,没有双写失败的情况。我们有两个机房,分别是机房 A 和机房 B。原创 2023-08-26 22:11:15 · 217 阅读 · 0 评论 -
订单超时怎么处理?我们用这种方案
背景在企业的商业活动中,订单是指交易双方的产品或服务交易意向。交易下单负责创建这个交易双方的产品或服务交易意向,有了这个意向后,买方可以付款,卖方可以发货。在电商场景下,买卖双方没有面对面交易,许多情况下需要通过超时处理自动关闭订单,下面是一个订单的流程:如上图所示,一个订单流程中有许多环节要用到超时处理,包括但不限于:买家超时未付款:比如超过15分钟没有支付,订单自动取消。商家超时未发货:比如商家超过1个月没发货,订单自动取消。原创 2023-07-03 16:55:43 · 306 阅读 · 0 评论 -
用开源管理系统做项目
基于 Spring+SpringMVC+Mybatis 分布式敏捷开发系统架构,提供整套公共微服务服务模块:集中权限管理(单点登录)、内容管理、支付中心、用户管理(支持第三方登录)、微信平台、存储系统、配置中心、日志分析、任务和通知等,支持服务治理、监控和追踪,努力为中小型企业打造全方位 J2EE 企业级开发解决方案。集成EF Core、多租户、缓存、数据校验、鉴权、事件总线、动态 API、通讯、远程请求、任务调度、gRPC 等众多黑科技。代码简洁、易扩展,让开发更简单、更通用、更流行!原创 2023-07-03 16:56:20 · 422 阅读 · 0 评论 -
真正的缓存之王
前言Guava Cache,他的优点是封装了get,put操作;提供线程安全的缓存操作;提供过期策略;提供回收策略;缓存监控。当缓存的数据超过最大值时,使用LRU算法替换。这一篇我们将要谈到一个新的本地缓存框架:Caffeine Cache。它也是站在巨人的肩膀上-Guava Cache,借着他的思想优化了算法发展而来。本文主要介绍Caffine Cache 的使用方式,以及Caffine Cache在SpringBoot中的使用。1. Caffine Cache 在算法上的优点-W-TinyLFU。原创 2023-07-03 16:52:26 · 786 阅读 · 0 评论 -
轻量级分布式日志标记追踪神器,十分钟即可接入到项目
TLog提供了一种最简单的方式来解决日志追踪问题,它不收集日志,也不需要另外的存储空间,它只是自动的对你的日志进行打标签,自动生成TraceId贯穿你微服务的一整条链路。并且提供上下游节点信息。适合中小型企业以及想快速解决日志追踪问题的公司项目使用。支持dubbo,dubbox,spring cloud三大RPC框架。TLog默认只打出spanId和traceId,以这种模板打出,当然你能自定义其模板。还能加入其它的标签头你只需要在springboot的$preApp:上游微服务节点名称。原创 2023-07-03 16:53:01 · 482 阅读 · 0 评论 -
SpringBoot分片上传、断点续传、大文件极速秒传功能
分片上传,就是将所要上传的文件,按照一定的大小,将整个文件分隔成多个数据块(我们称之为Part)来进行分别上传,上传完之后再由服务端对所有上传的文件进行汇总整合成原始的文件。断点续传是在下载或上传时,将下载或上传任务(一个文件或一个压缩包)人为的划分为几个部分,每一个部分采用一个线程进行上传或下载,如果碰到网络故障,可以从已经上传或下载的部分开始继续上传或者下载未完成的部分,而没有必要从头开始上传或者下载。本文的断点续传主要是针对断点上传场景。原创 2023-07-03 16:52:04 · 499 阅读 · 0 评论 -
推出跨库高效数据同步神器
DataX 是阿里云 DataWorks 数据集成 的开源版本,主要就是用于实现数据间的离线同步。DataX 致力于实现包括关系型数据库(MySQL、Oracle 等)、HDFS、Hive、ODPS、HBase、FTP 等各种异构数据源(即不同的数据库)间稳定高效的数据同步功能。为了解决异构数据源同步问题,DataX 将复杂的网状同步链路变成了星型数据链路,DataX 作为中间传输载体负责连接各种数据源;当需要接入一个新的数据源时,只需要将此数据源对接到 DataX,便能跟已有的数据源作为无缝数据同步。原创 2023-07-03 16:50:52 · 228 阅读 · 0 评论 -
负载均衡 LVS vs Nginx 大对比
今天总结一下负载均衡中LVS与Nginx的区别,好几篇博文一开始就说LVS是单向的,Nginx是双向的,我个人认为这是不准确的,LVS三种模式中,虽然DR模式以及TUN模式只有请求的报文经过Director,但是NAT模式,Real Server回复的报文也会经过Director Server地址重写:首先要清楚的一点是,LVS是一个四层的负载均衡器,虽然是四层,但并没有TCP握手以及分手,只是偷窥了IP等信息,而Nginx是一个七层的负载均衡器,所以效率势必比四层的LVS低很多,但是可操作性比LVS高,后原创 2023-07-03 16:46:56 · 1376 阅读 · 0 评论 -
一碰就头疼的 Kafka 消息重复问题,立马解决
数据重复这个问题其实也是挺正常,全链路都有可能会导致数据重复。通常,消息消费时候都会设置一定重试次数来避免网络波动造成的影响,同时带来副作用是可能出现消息重复。原创 2023-07-03 16:48:10 · 2283 阅读 · 0 评论 -
最全的redis常用命令
如果 key 已经存在并且是一个字符串, APPEND 命令将 指定value 追加到改 key 原来的值(value)的末尾。对一个列表进行修剪(trim),就是说,让列表只保留指定区间内的元素,不在指定区间之内的元素都将被删除。移出并获取列表的最后一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。移出并获取列表的第一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。计算给定的一个或多个有序集的交集并将结果集存储在新的有序集合 key 中。原创 2023-07-03 16:22:20 · 17386 阅读 · 0 评论 -
一款强大的开源认证和访问控制利器:KeyCloak
我们可参考这两套主题的代码,编写我们自己的主题。上文,我们创建的Client都是public 类型的,而现在,其实只有Zuul需要对外,其他服务都是经过Zuul或者Feign传递Token的。Keycloak利用policy的概念,以及如何通过提供聚合policy的概念来定义它们,您可以在其中构建“policy 中的 policy”,并仍然控制评估的行为。当然,也可以不创建Realm,直接用 Master 这个Realm,不过一般来说,为了资源的隔离,以及更好的安全性不太建议与管理员共用Realm。原创 2023-06-26 12:59:20 · 1517 阅读 · 0 评论 -
Kafka 消息重复问题
数据重复这个问题其实也是挺正常,全链路都有可能会导致数据重复。通常,消息消费时候都会设置一定重试次数来避免网络波动造成的影响,同时带来副作用是可能出现消息重复。遇到异常,基本解决措施都是。leader分区不可用了,抛异常,等待选出新leader分区。Controller所在Broker挂了,抛异常,等待Controller重新选举。场景三:网络异常、断网、网络分区、丢包等,抛异常,等待网络恢复。poll一批数据,处理完毕还没提交offset,机子宕机重启了,又会poll。原创 2023-06-26 12:57:24 · 977 阅读 · 0 评论 -
Redis 官方可视化工具,功能真心强大
基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能。支持基于 SSL/TLS 的连接,同时还可以在界面上进行内存分析;:配置 RedisInsight 的 IP 地址(:配置 RedisInsight 的日志存放路径(:配置 RedisInsight 的数据存放路径(:配置 RedisInsight 的监听端口(原创 2023-06-26 12:53:49 · 1006 阅读 · 0 评论 -
从根上告诉你,为什么有了 HTTP 协议,还需要 RPC
用于区分。原创 2023-06-26 12:52:50 · 110 阅读 · 0 评论 -
SpringBoot+WebSocket实现服务端、客户端
百度百科介绍:WebSokcet在公司实际使用websocket开发,一般来都是这样的架构,首先websocket服务端是一个单独的项目,其他需要通讯的项目都是以客户端来连接,由服务端控制消息的发送方式(群发、指定发送)。但是也会有服务端、客户端在同一个项目当中,具体看项目怎么使用。本文呢,采用的是服务端与客户端分离来实现,包括使用springboot搭建websokcet服务端、html5客户端、springboot后台客户端, 具体看下面代码。原创 2023-06-26 12:47:46 · 8740 阅读 · 2 评论 -
美团动态线程池实践思路,开源了
基于以上背景分析,我们对线程池 ThreadPoolExecutor 做一些扩展增强,主要实现以下目标」❝1.实现对运行中线程池参数的动态修改,实时生效2.实时监控线程池的运行状态,触发设置的报警策略时报警,报警信息推送办公平台3.定时采集线程池指标数据,配合像 grafana 这种可视化监控平台做大盘监控❞「经过多个版本的迭代,目前最新版本 v1.0.9 具有以下特性」✅「代码零侵入」:所有配置都放在配置中心,对业务代码零侵入「轻量简单」:基于 SpringBoot 实现,引入starter。原创 2023-06-26 12:46:56 · 150 阅读 · 0 评论 -
风控系统就该这么设计(万能通用),稳的一批
目前我们业务有使用到非常多的AI能力,如ocr识别、语音测评等,这些能力往往都比较费钱或者费资源,所以在产品层面也希望我们对用户的能力使用次数做一定的限制,因此风控是必须的!自然日+自然小时计数 这里并不能单纯地串联两个判断,因为如果自然日的判定通过,而自然小时的判定不通过的时候,需要回退,自然日跟自然小时都不能计入本次调用!很多限制值在首次设置的时候,基本上都是拍定的一个值,后续需要调整的可能性是比较大的,因此可调整并实时生效是必须的。如前文提到的,两个的结合实际上并不是单纯的拼凑,需要处理回退逻辑。原创 2023-06-26 12:48:21 · 269 阅读 · 0 评论 -
月增千万的数据,我用单体+单库扛下了所有
看到这里,对于库内分表篇的内容也接近了尾声,有小伙伴也许会疑惑:那如果我每月的数据量更大怎么办呢?比如前面的例子中,如果再投入了多批机器怎么办?每月的数据量达到3000W、6000W.....甚至上亿怎么办?如若你存在这块的顾虑,其实大可不必担心,因为咱们既然可以按月分表,那能否按半月为周期分表呢?能否按星期分表呢?能否以三天、一天为一个维度分表呢?答案显然是可以的,所以数据量无论有多大,都可能按不同的周期来划分表。原创 2023-06-26 12:47:20 · 169 阅读 · 0 评论 -
2万字系统总结,帮你实现 Linux 命令自由
Linux系统内核指的是由负责维护,提供硬件抽象层、硬盘及文件系统控制及多任务功能的系统核心程序。Linux发行套件系统是我们常说的Linux操作系统,也即是由Linux内核与各种常用软件的集合产品。「总结:真正的Linux指的是系统内核,而我们常说的Linux指的是“发行版完整的包含一些基础软件的操作系统”。相信通过本文的学习,你应该会对Linux有一个更加全面的认识。原创 2023-06-25 21:13:59 · 279 阅读 · 0 评论 -
Redis队列实现Java版秒杀系统(无脚本、可用于生产)
如此,每个请求都无需经过加锁操作,直接利用redis的单线程特性,即可实现高并发下的秒杀:请求到达redis,redis会逐个执行,每一次执行要么返回一个值,要么返回null。赶工分布式秒杀,没想到如此基本的内容,竟没找到一个靠谱的实现,从上午写到现在(周末晚8点)一顿饭没吃,被网上过于demo的资源逼的,忍饿怒出此文。demo里同样没写个重试,抢不到锁就失败,醉了,不过就算写重新抢锁的机制,那么几十个上百个线程不断抢锁,想想是个挺恐怖的事,更别提高并发了。原创 2023-06-25 21:07:33 · 900 阅读 · 1 评论 -
Redis 分布式锁如何实现自动续期
如果锁当前还是被占用的,那么等待释放锁的消息,具体实现使用了信号量 Semaphore 来阻塞线程,当锁释放并发布释放锁的消息后,信号量的 release() 方法会被调用,此时被信号量阻塞的等待队列中的一个线程就可以继续尝试获取锁了。死循环去获取锁,而是利用了 Redis 的发布订阅机制,通过 await 方法阻塞等待锁的进程,有效的解决了无效的锁申请浪费资源的问题。如果这个锁的过期时间是30秒,但是业务运行超过了30秒,比如40秒,当业务运行到30秒的时候,锁过期了,其他客户端拿到了这个锁,怎么办。原创 2023-06-25 21:06:50 · 1550 阅读 · 0 评论 -
零拷贝、MMAP、堆外内存
前言零拷贝、MMAP、堆外内存傻傻搞不明白。0.0虚拟内存:将用户逻辑内存与物理内存分开。内核态():非特权区域, 在该区域执行的代码就不能直接访问硬件设备。用户进程所在区域。用户态(User Mode):内核有特别的权利,它能与设备控制器通讯, 控制着用户区域进程的运行状态。DMA直接内存存取():是一种允许外围设备(硬件子系统)直接访问系统主内存的机制。接管了数据读写的工作,不需要CPU再参与I/O中断的处理,从而减轻了CPU的负担。硬件通常不能直接访问用户空间。原创 2023-06-25 21:03:47 · 171 阅读 · 0 评论 -
撸了个牛逼的项目,可在14个平台运行
Flex用来为盒状模型提供最大的灵活性。任何一个容器都可以指定为 Flex 布局。代码示例如下:.box{行内元素也可以使用 Flex 布局。代码示例如下:.box{采用 Flex 布局的元素称为 Flex 容器(flex container),简称容器,如图3.1所示。它的所有子元素自动成为容器成员,称为 Flex 项目(flex item),简称项目。图3.1 flex container 示意图。原创 2023-06-25 21:01:53 · 375 阅读 · 0 评论 -
9个你应该知道的支付系统开源项目
项目简介:Fastpay 的目标是打造一款开源的、轻量级的、微服务化的、可共私有云部署的、可定制化的集成聚合支付和资金清结算于一体的统一支付系统,满足互联网企业业务系统的收款和资金处理等需求。项目简介:龙果支付系统核心目标是汇聚所有主流支付渠道,打造一款轻量、便捷、易用,且集支付、资金对账、资金清结算于一体的支付系统,满足互联网业务系统的收款和业务资金管理需求。目前已经接入支付渠道:微信(公众号支付、扫码支付、APP支付、H5支付)、支付宝(电脑网站支付、手机网站支付、APP支付、当面付)。原创 2023-06-25 21:01:36 · 2171 阅读 · 0 评论 -
RockeMQ 是如何通过 mmap 大幅提升单机吞吐量的
可靠的FIFO和严格有序的消息队列中间件。2011年:业界出现了现在被很多大数据领域所推崇的Kafka消息引擎,阿里巴巴在研究了Kafka的整体机制和架构设计之后,基于Kafka的设计使用Java进行了完全重写并推出了MetaQ 1.0版本,主要是用于解决顺序消息和海量堆积的问题。我们知道,在操作系统的中,数据通常都是被放在磁盘中的,只有在需要计算的时候,才会将数据加载到内存中,而每次加载的单位都是以“页”作为基础,假设我们需要访问一块存在于磁盘,但是没有被加载到内存中的数据,这种情况,我们称之为。原创 2023-06-25 21:00:30 · 1673 阅读 · 0 评论 -
图文详解红黑树
在MySQL中,这里所说的真实数据,可能是行的全部数据(如Innodb的聚簇索引),也可能只是行的主键(如Innodb的辅助索引),或者是行所在的地址(如MyIsam的非聚簇索引)。与AVL树相比,红黑树并不追求严格的平衡,而是大致的平衡:只是确保从根到叶子的最长的可能路径不多于最短的可能路径的两倍长。二叉查找树(BST,Binary Search Tree),也叫二叉排序树,在二叉树的基础上需要满足:任意节点的左子树上所有节点值不大于根节点的值,任意节点的右子树上所有节点值不小于根节点的值。原创 2023-06-25 20:56:57 · 118 阅读 · 0 评论 -
为什么一定要替换掉 SpringBoot 框架中的 Tomcat
在SpringBoot框架中,我们使用最多的是Tomcat,这是SpringBoot默认的容器技术,而且是内嵌式的Tomcat。同时,SpringBoot也支持Undertow容器,我们可以很方便的用Undertow替换Tomcat,而Undertow的性能和内存使用方面都优于Tomcat,那我们如何使用Undertow技术呢?本文将为大家细细讲解。SpingBoot中我们既可以使用Tomcat作为Http服务,也可以用Undertow来代替。Undertow在高并发业务场景中,性能优于Tomcat。原创 2023-06-25 20:57:39 · 298 阅读 · 0 评论 -
Java中一行代码搞定Http请求,强得离谱
在Java的世界中,Http客户端之前一直是Apache家的HttpClient占据主导,但是由于此包较为庞大,API又比较难用,因此并不使用很多场景。而新兴的OkHttp、Jodd-http固然好用,但是面对一些场景时,学习成本还是有一些的。很多时候,我们想追求轻量级的Http客户端,并且追求简单易用。而OKHttp是一套处理 HTTP 网络请求的依赖库,由 Square 公司设计研发并开源,目前可以在 Java 和 Kotlin 中使用。原创 2023-06-16 12:02:28 · 240 阅读 · 0 评论 -
Spring Boot 实现万能文件在线预览,已开源,真香
推荐一个用Spring Boot搭建的文档在线预览解决方案:kkFileView,一款成熟且开源的文件文档在线预览项目解决方案,对标业内付费产品有【永中office】【office365】【idocv】等,免费!原创 2023-06-16 12:01:43 · 308 阅读 · 0 评论 -
看了我写的设计模式,全公司同事都开始悄悄模仿了
一个抽象类公开定义了执行它的方法的方式/模板,它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行,属于行为型模式。这 3 只企鹅,因为 “吃饭,睡觉” 都一样,所以我们可以直接实现出来,原创 2023-06-16 12:00:23 · 93 阅读 · 0 评论 -
SpringBoot + Disruptor = 王炸
1.Disruptor 是英国外汇交易公司LMAX开发的一个高性能队列,研发的初衷是解决内存队列的延迟问题(在性能测试中发现竟然与I/O操作处于同样的数量级)。基于 Disruptor 开发的系统单线程能支撑每秒 600 万订单,2010 年在 QCon 演讲后,获得了业界关注。2.Disruptor是一个开源的Java框架,它被设计用于在生产者—消费者(producer-consumer problem,简称PCP)问题上获得尽量高的吞吐量(TPS)和尽量低的延迟。原创 2023-06-16 12:00:52 · 207 阅读 · 0 评论