自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(132)
  • 收藏
  • 关注

原创 2020-09-11

mapreduce是如何在分布式系统中运行的?wordcount如何用mapreduce实现,如何用spark编程实现?spark为什么比mapreduce快?

2020-09-11 22:47:56 93

原创 2020-09-11

数据加密算法有哪些种类?数字签名是什么意思?如何实现?

2020-09-11 22:45:36 93

原创 2020-09-11

导致系统故障无法访问的原因有哪些?保障系统高可用的方案有哪些,请列举并简述?

2020-09-11 22:42:29 120

原创 2020-09-11

为什么在系统性能测试的时候,随着并发请求数的增加,错误响应和响应超时会快速增加?

2020-09-11 20:25:38 74

原创 2020-09-11

什么是事件驱动架构,简单描述一个应用场景和架构方案?

2020-09-11 19:10:14 92

原创 2020-09-11

系统架构中的缓存起什么作用?通读缓存和旁路缓存有什么区别?缓存是提高性能最好的方式,一般来说,缓存有以下三种模式。Cache Aside 更新模式这是最常用的设计模式了,其具体逻辑如下。失效:应用程序先从 cache 取数据,没有得到,则从数据库中取数据,成功后,放到缓存中。命中:应用程序从 cache 中取数据,取到后返回。更新:先把数据存到数据库中,成功后,再让缓存失效。Read/Write Through 更新模式在上面的 Cache Aside 套路中,应用代码需要维护两个数据存储,一个是

2020-09-11 18:41:45 80

原创 2020-09-11

如何写一个软件设计文档,文档中应该包含哪些内容?对于规模不太大的软件系统,我们可以将概要设计文档和详细设计文档合并成一个设计文档。文档开头是设计概述,简单描述业务场景要解决的核心问题领域是什么。至于业务场景,应该在专门的需求文档中描述,但是在设计文档中,必须要再简单描述一下,以保证设计文档的完整性,这样,即使脱离需求文档,阅读者也能理解主要的设计。此外,在设计概述中,还需要描述设计的非功能约束,比如关于性能、可用性、维护性、安全性,甚至开发和部署成本方面的设计目标。然后就是具体的设计了,第一张设计图应

2020-09-11 18:36:13 183

原创 2020-09-11

怎么理解领域驱动技术DDD,DDD如何落地实践,方法和步骤是怎样的?

2020-09-11 16:31:23 76

原创 2020-09-10

juit中使用了什么样的设计模式?

2020-09-10 19:49:04 51

原创 2020-09-10

什么是软件框架,软件框架遵询什么样的设计原则?举个例子说明?

2020-09-10 16:10:54 60

原创 2020-09-10

什么是软件设计的开闭原则?如何实现开闭原则,有哪些方法?软件实体(模块、类、函数等等)应该对扩展是开放的,对修改是关闭的。通俗的说就是,软件功能可以扩展,但是软件实体不可以被修改。在代码中看到 else 或者 switch/case 关键字的时候,基本可以判断违反开闭原则了。设计模式中很多模式其实都是用来解决软件的扩展性问题的,也是符合开闭原则的。策略模式适配器模式观察者模式模板方法模式实现开闭原则的关键是抽象。当一个模块依赖的是一个抽象接口的时候,就可以随意对这个抽象接口进行扩展,这个时

2020-09-10 16:03:00 68

原创 2020-09-10

非阻塞网络通信实现的底层原理是什么?

2020-09-10 11:46:33 68

原创 2020-09-09

http请求的端口号记录在哪一层通信协议中,如何通过链路层协议转换实现的web服务器集群负载均衡?

2020-09-09 23:48:58 118 1

原创 2020-09-09

计算机底层,锁是如何实现的?jvm中的synchronized是如何实现的?和硬件相关的一般来说,根本上就是关中断,然后执行一个操作,然后开中断。关了中断,就无法进行任务调度了,所以在关中断到开中断之间的操作是不会被打断的。synchronized代码块是由一对儿monitorenter/monitorexit指令实现的,Monitor对象是同步的基本实现单元。在Java 6之前,Monitor的实现完全是依靠操作系统内部的互斥锁,因为需要进行用户态到内核态的切换,所以同步操作是一个无差别的重量级

2020-09-09 23:38:06 81

原创 2020-09-09

什么是线程安全?单例对象是线程安全的吗?线程安全指的是高并发情况下,比如变量的操作不存在表示错误。单例模式与线程安全没有直接关系。

2020-09-09 23:31:56 66

原创 2020-09-09

什么是NP问题?如何用动态规划解背包问题?红黑树和二叉平衡搜索树有什么区别?

2020-09-09 22:41:42 76

原创 2020-09-09

如何遍历一棵树?如何用组合设计模式遍历一棵树?

2020-09-09 22:16:14 73

原创 2020-09-09

HashSet 的 contains 方法判断元素是否在 HashSet 中,同样是 Set 的 TreeSet 其 contains 方法和 HashSet 有什么区别吗?第二个问题:HashSet本质上就是HashMap的key组成的不重复的元素集合,contains方法其实就是根据hashcode和equals去判断相等的TreeSet本质TreeMap的key组成的,数据结构是红黑树,是自带排序功能的,可以在放入元素的时候指定comparator(比较器),或者是放入的元素要实现Compara

2020-09-09 22:14:48 78

原创 2020-09-08

在实现 equals 时,我是先通过 getClass 方法判断两个对象的类型,你可能会想到还可以使用 instanceof 来判断。你能说说这两种实现方式的区别吗?instanceof进行类型检查规则是:你是该类或者是该类的子类;getClass获得类型信息采用==来进行检查是否相等的操作是严格的判断。不会存在继承方面的考虑;...

2020-09-08 23:08:06 67

原创 2020-09-08

对象判等和比较。首先,我们要注意 equals 和 == 的区别。业务代码中进行内容的比较,针对基本类型只能使用 ==,针对 Integer、String 在内的引用类型,需要使用 equals。Integer 和 String 的坑在于,使用 == 判等有时也能获得正确结果。其次,对于自定义类型,如果类型需要参与判等,那么务必同时实现 equals 和 hashCode 方法,并确保逻辑一致。如果希望快速实现 equals、hashCode 方法,我们可以借助 IDE 的代码生成功能,或使用 Lomb

2020-09-08 23:04:28 97

原创 2020-09-08

关于索引的两个误区。第一个误区是,考虑到索引的维护代价、空间占用和查询时回表的代价,不能认为索引越多越好。索引一定是按需创建的,并且要尽可能确保足够轻量。一旦创建了多字段的联合索引,我们要考虑尽可能利用索引本身完成数据查询,减少回表的成本。第二个误区是,不能认为建了索引就一定有效,对于后缀的匹配查询、查询中不包含联合索引的第一列、查询条件涉及函数计算等情况无法使用索引。此外,即使 SQL 本身符合索引的使用条件,MySQL 也会通过评估各种查询方式的代价,来决定是否走索引,以及走哪个索引。因此,在尝试通

2020-09-08 22:58:15 75

原创 2020-09-08

常见的使用数据库事务的方式,即 Spring 声明式事务,使用上可能遇到的三类坑,包括:第一,因为配置不正确,导致方法上的事务没生效。我们务必确认调用 @Transactional 注解标记的方法是 public 的,并且是通过 Spring 注入的 Bean 进行调用的。第二,因为异常处理不正确,导致事务虽然生效但出现异常时没回滚。Spring 默认只会对标记 @Transactional 注解的方法出现了 RuntimeException 和 Error 的时候回滚,如果我们的方法捕获了异常,

2020-09-08 22:54:41 62

原创 2020-09-08

TCP 长连接的方式是怎么实现“当有消息需要发送给某个用户时,能够准确找到这个用户对应的网络连接”?首先用户有一个登陆的过程: (1)tcp客户端与服务端通过三次握手建立tcp连接;(2)基于该连接客户端发送登陆请求;(3)服务端对登陆请求进行解析和判断,如果合法,就将当前用户的uid和标识当前tcp连接的socket描述符(也就是fd)建立映射关系; (4)这个映射关系一般是保存在本地缓存或分布式缓存中。然后,当服务端收到要发送给这个用户的消息时,先从缓存中根据uid查找fd,如果找到,就基于fd将消

2020-09-08 19:11:46 80

原创 2020-09-08

能从索引表里获取到最近联系人所需要的信息,为什么还需要单独的联系人表呢?如果从索引表中获取一个用户的所有联系人信息(包括最后一条聊天内容和时间)的话,SQL语句中会有分组后取top 1的操作,性能不理想; 另外当前用户与单个联系人之间的未读数需要维护,用联系人表的一个字段来存储,比用索引表方便许多。...

2020-09-08 18:16:46 60

原创 2020-09-08

im消息存储中,内容表和索引表如果需要分库处理,应该按什么字段来哈希? 索引表可以和内容表合并成一个表吗?这里需要考虑一个问题,我们在查询两个人之间的历史消息的时候是用户维度的查询还是消息维度的查询?如果按消息id哈希,查询两个人之间的历史消息在只有uid的情况下该怎么查呢?考虑下消息索引表的访问模式,对于索引表最终要求的是尽量能提升获取的效率,所以如果需要有索引表,应该是uid维度的查询会更高效一些。内容表应该按主键消息ID来哈希做分库分表处理,这样便于定位某一条具体的消息;索引表应该按索引的用户U

2020-09-08 18:13:35 58

原创 2020-09-08

消息一定需要在服务端的存储服务里进行存储吗?需要看需求。存储在服务端的作用:1.会话一方用户不在线,上线时进行消息推送。2.内容审查,监管,电子证据,法律要求。3.数据分析,舆情分析。服务端存储需要更多考虑成本和数据安全,也和产品定位有关,比如不需要支持消息多终端同步的应用,可以不在服务端进行存储。当然,还需要考虑国内监管机制是否允许的问题。存储在客户端,多终端登录时候同步比较困难。即时消息可以放到MQ中,或者缓存中,使用数据抽取工具周期性的将数据提交服务器,进行持久化。服务器存储历史数据和近

2020-09-08 17:41:14 58

原创 2020-09-08

即时消息系统所适用的业务场景需求特性实时性,保证消息实时触达是互动场景的必备能力。可靠性,“不丢消息”和“消息不重复”是系统值得信赖的前置条件。一致性,“多用户”“多终端”的一致性体验能大幅提升 IM 系统的使用体验。安全性,“数据传输安全”“数据存储安全”“消息内容安全“三大保障方面提供全面隐私保护。...

2020-09-08 17:33:28 59

原创 2020-09-07

HTTP 调用最常遇到的超时、重试和并发问题。连接超时代表建立 TCP 连接的时间,读取超时代表了等待远端返回数据的时间,也包括远端程序处理的时间。在解决连接超时问题时,我们要搞清楚连的是谁;在遇到读取超时问题的时候,我们要综合考虑下游服务的服务标准和自己的服务标准,设置合适的读取超时时间。此外,在使用诸如 Spring Cloud Feign 等框架时务必确认,连接和读取超时参数的配置是否正确生效。对于重试,因为 HTTP 协议认为 Get 请求是数据查询操作,是无状态的,又考虑到网络出现丢包是比较常

2020-09-08 11:51:42 100

原创 2020-09-07

业务代码使用了线程池异步处理一些内存中的数据,但通过监控发现处理得非常慢,整个处理过程都是内存中的计算不涉及 IO 操作,也需要数秒的处理时间,应用程序 CPU 占用也不是特别高,有点不可思议。经排查发现,业务代码使用的线程池,还被一个后台的文件批处理任务用到了。或许是够用就好的原则,这个线程池只有 2 个核心线程,最大线程也是 2,使用了容量为 100 的 ArrayBlockingQueue 作为工作队列,使用了 CallerRunsPolicy 拒绝策略:private static Threa

2020-09-07 19:06:11 73

原创 2020-09-07

某项目生产环境时不时有报警提示线程数过多,超过 2000 个,收到报警后查看监控发现,瞬时线程数比较多但过一会儿又会降下来,线程数抖动很厉害,而应用的访问量变化不大。为了定位问题,我们在线程数比较高的时候进行线程栈抓取,抓取后发现内存中有 1000 多个自定义线程池。一般而言,线程池肯定是复用的,有 5 个以内的线程池都可以认为正常,而 1000 多个线程池肯定不正常。在项目代码里,我们没有搜到声明线程池的地方,搜索 execute 关键字后定位到,原来是业务代码调用了一个类库来获得线程池,类似如下的业

2020-09-07 19:03:58 119

原创 2020-09-07

用户注册后,我们调用一个外部服务去发送短信,发送短信接口正常时可以在 100 毫秒内响应,TPS 100 的注册量,CachedThreadPool 能稳定在占用 10 个左右线程的情况下满足需求。在某个时间点,外部短信服务不可用了,我们调用这个服务的超时又特别长, 比如 1 分钟,1 分钟可能就进来了 6000 用户,产生 6000 个发送短信的任务,需要 6000 个线程,没多久就因为无法创建线程导致了 OOM,整个应用程序崩溃。因此,我同样不建议使用 Executors 提供的两种快捷的线程池,原因

2020-09-07 19:00:32 78

原创 2020-09-07

现在有10个接口访问日志文件,每个日志文件大小约300MB,每个文件里的日志都是按照时间戳从小到大排序的。你希望将这10个较小的日志文件,合并为1个日志文件,合并之后的日志仍然按照时间戳从小到大排列。如果处理上述排序任务的机器内存只有1GB,你有什么好的解决思路,能“快速”地将这10个日志文件合并吗?先构建十条io流,分别指向十个文件,每条io流读取对应文件的第一条数据,然后比较时间戳,选择出时间戳最小的那条数据,将其写入一个新的文件,然后指向该时间戳的io流读取下一行数据,然后继续刚才的操作,比较选出最

2020-09-07 18:53:18 291

原创 2020-09-07

在一个类里有两个 int 类型的字段 a 和 b,有一个 add 方法循环 1 万次对 a 和 b 进行 ++ 操作,有另一个 compare 方法,同样循环 1 万次判断 a 是否小于 b,条件成立就打印 a 和 b 的值,并判断 a>b 是否成立。@Slf4jpublic class Interesting {volatile int a = 1;volatile int b = 1;public void add() {log.info(“add start”);for (int

2020-09-07 14:46:11 91 1

原创 2020-09-07

在排查一个生产性能问题时,我们发现一段简单的非数据库操作的业务逻辑,消耗了超出预期的时间,在修改数据时操作本地缓存比回写数据库慢许多。查看代码发现,开发同学使用了 CopyOnWriteArrayList 来缓存大量的数据,而数据变化又比较频繁。CopyOnWrite 是一个时髦的技术,不管是 Linux 还是 Redis 都会用到。在 Java 中,CopyOnWriteArrayList 虽然是一个线程安全的 ArrayList,但因为其实现方式是,每次修改数据时都会复制一份数据出来,所以有明显的适用

2020-09-07 11:45:33 63

原创 2020-09-07

computeIfAbsent 为什么如此高效呢?答案就在源码最核心的部分,也就是 Java 自带的 Unsafe 实现的 CAS。它在虚拟机层面确保了写入数据的原子性,比加锁的效率高得多:static final <K,V> boolean casTabAt(Node<K,V>[] tab, int i,Node<K,V> c, Node<K,V> v) {return U.compareAndSetObject(tab, ((long)i <

2020-09-07 11:42:21 91

原创 2020-09-07

使用了线程安全的并发工具,并不代表解决了所有线程安全问题。ConcurrentHashMap 只能保证提供的原子性读写操作是线程安全的。ConcurrentHashMap 对外提供的方法或能力的限制:使用了 ConcurrentHashMap,不代表对它的多个操作之间的状态是一致的,是没有其他线程在操作它的,如果需要确保需要手动加锁。诸如 size、isEmpty 和 containsValue 等聚合方法,在并发情况下可能会反映 ConcurrentHashMap 的中间状态。因此在并发情况下,这些

2020-09-07 11:41:26 197

原创 2020-09-07

在生产上遇到一个诡异的问题,有时获取到的用户信息是别人的?查看代码后,发现使用了 ThreadLocal 来缓存获取到的用户信息。ThreadLocal 适用于变量在线程间隔离,而在方法或类间共享的场景。如果用户信息的获取比较昂贵(比如从数据库查询用户信息),那么在 ThreadLocal 中缓存数据是比较合适的做法。但,这么做为什么会出现用户信息错乱的 Bug 呢?在 Tomcat 这种 Web 服务器下跑的业务代码,本来就运行在一个多线程环境(否则接口也不可能支持这么高的并发),并不能认为没有显式开

2020-09-07 11:38:23 74

原创 2020-09-06

JVM内存管理中有个“堆栈”的概念。栈内存用来存储局部变量和方法调用,堆内存用来存储Java中的对象。那JVM里面的“栈”跟函数调用的“栈”是不是一回事呢?如果不是,那它为什么又叫作“栈”呢?...

2020-09-07 06:52:01 53

原创 2020-09-06

为什么函数调用要用“栈”来保存临时变量呢?用其他数据结构不行吗?其实,我们不一定非要用栈来保存临时变量,只不过如果这个函数调用符合后进先出的特性,用栈这种数据结构来实现,是最顺理成章的选择。从调用函数进入被调用函数,对于数据来说,变化的是什么呢?是作用域。所以根本上,只要能保证每进入一个新的函数,都是一个新的作用域就可以。而要实现这个,用栈就非常方便。在进入被调用函数的时候,分配一段栈空间给这个函数的变量,在函数结束的时候,将栈顶复位,正好回到调用函数的作用域内。...

2020-09-06 22:36:44 47

原创 2020-09-06

如何判断一个字符串是否是回文字符串的问题,我想你应该听过,我们今天的思题目就是基于这个问题的改造版本。如果字符串是通过单链表来存储的,那该如何来判断是一个回文串呢?你有什么好的解决思路呢?相应的时间空间复杂度又是多少呢?...

2020-09-06 22:29:55 54

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除