java-route
java-route copied to clipboard
Java technology route
本文参考翻译自 [《Redis Sentinel Documentation》](http://redis.io/topics/sentinel) 概述 Redis-Sentinel是Redis官方推荐的高可用性(HA)解决方案,当用Redis做Master-slave的高可用方案时,假如master宕机了,Redis本身(包括它的很多客户端)都没有实现自动进行主备切换,而Redis-sentinel本身也是一个独立运行的进程,它能监控多个master-slave集群,发现master宕机后能进行自懂切换。 它的主要功能有以下几点 - 不时地监控redis是否按照预期良好地运行; - 如果发现某个redis节点运行出现状况,能够通知另外一个进程(例如它的客户端); - 能够进行自动切换。当一个master节点不可用时,能够选举出master的多个slave(如果有超过一个slave的话)中的一个来作为新的master,其它的slave节点会将它所追随的master的地址改为被提升为master的slave的新地址。 Sentinel支持集群 很显然,只使用单个sentinel进程来监控redis集群是不可靠的,当sentinel进程宕掉后(sentinel本身也有单点问题,single-point-of-failure)整个集群系统将无法按照预期的方式运行。所以有必要将sentinel集群,这样有几个好处: - 即使有一些sentinel进程宕掉了,依然可以进行redis集群的主备切换; - 如果只有一个sentinel进程,如果这个进程运行出错,或者是网络堵塞,那么将无法实现redis集群的主备切换(单点问题); - 如果有多个sentinel,redis的客户端可以随意地连接任意一个sentinel来获得关于redis集群中的信息。 Sentinel版本 Sentinel当前最新的稳定版本称为Sentinel 2(与之前的Sentinel 1区分开来)。随着redis2.8的安装包一起发行。安装完Redis2.8后,可以在redis2.8/src/里面找到Redis-sentinel的启动程序。 强烈建议: 如果你使用的是redis2.6(sentinel版本为sentinel 1),你最好应该使用redis2.8版本的sentinel 2,因为sentinel 1有很多的Bug,已经被官方弃用,所以强烈建议使用redis2.8以及sentinel...
http://www.hollischuang.com/archives/1459
一、背景 当前, 几乎所有的手机应用都不会是单机运行在机器中,而是配合一个或者多个后台服务共同完成所有操作。举个例子,一个微博客户端,在用户进行看帖、发帖、顶踩等操作时,都会将请求发送给微博的后台服务器进行处理。这种交互方式就是典型的C/S架构,交互图大概是介样子的: 然而实际应用场景中,并不会只有一个后台服务,而是多个服务分而治之。比如上面例子中的微博客户端,可能会与后台的帖子服务器、点赞服务器、图片服务器(不要在意命名这些细节)等多个服务器产生交互请求。于是,这个时候的交互图变成了: 上面都还只是提到了内部服务,那如果再加上一些必要的外联系统呢(比如广告服务、新闻服务、内容推荐服务、搜索服务等第三方服务)?可以看到交互图有些丧心病狂了: 对于客户端来说,无论是内部服务还是外联服务,都是一些独立的外部server,客户端无法干涉也不应该干涉。那么在客户端的开发或测试过程中,应该如何让这些server“配合”做测试和联调呢?最简单粗暴的方式就是直接连接外部系统。但是这种方式有很大的缺陷:我们无法控制这些外部系统,只能覆盖到最基本的场景。同时这种方式也受到了很大的限制,万一这些外部系统还未开发完成或者暂时无法提供服务,那我们的联调、测试工作将被block住。所以,最可靠的方式就是自己构造或者模拟一些这样的server,然后再随意控制server的响应以覆盖所有联调和测试场景。这便是mock平台的作用。 二、现有mock平台的局限和新解决方案 当前业界也存在许多优秀的mock平台或工具,比如GoogleMock, EasyMock, MockServer等,但是这些mock平台工具多少存在着一些局限性: 1. 作为单元测试工具,只适用于单元测试而无法适用功能测试或者性能测试,且一般都是某种语言专用,比如GoogleMock就是一个C++的mock框架; 2. 可以作为http mock平台使用,但没有提供API随意添加、修改mock数据设置; 3. 开放了API,但mock节点只有一个,当两个相同业务同时使用时容易造成冲突(请求url相同,后面的配置会覆盖前者); 4. 节点单一且数据没有缓存机制,性能表现差,无法支持大数据测试; 5. 没有随机输出的功能,不适用于稳定性or性能测试; 6. 其它局限,比如扩展性差等。 为了解决以上种种问题,我特此设计和实现了一个高性能分布式的Mock解决方案。废话不多说,来看具体的设计思路吧。 三、整体架构和设计思路 名词解释 MCS:Mock Control Server,即Mock平台的管理主控点,专用于维护、管理Mock节点,提供API配置、管理Mock数据。 MSN:Mock...
静态编译优化和动态编译优化最大的不同是他们在编译时所得到的信息量的不同。静态编译在运行程序之前就把所有的执行代码编译完,这时编译器所接受的编译信息量是不够多的。比如说:某个函数是否是大量地被调用了,函数的实参是不是一直是一个常数,等等。 动态编译之于静态编译,缺点是它需要即时编译代码,但是有一个优点---编译器可以获得静态编译期所没有的信息。比如:通过运行时的profiling可以知道哪些函数是被大量使用的。在哪些execution path上哪些函数的参数一直都没有变,等等。不要小看这些信息,当即时编译器了解这些信息之后可以在短时间内编译出比静态编译器更优质的二进制码。举例来说,一般程序也遵循90-10原则,即运行时的90%里计算机是在处理其中10%的代码,寻找到这些执行热点代码进行深度优化能得到比静态编译更好的性能(因为已知更多信息量)。 然而现实是:即时编译的开销非常大,暂时还不能超越静态编译的总体性能。不过,一个动态语言(如JAVA,Python)有着静态语言(如C++)所没有的各种优势,必然是将来程序语言发展的方向。伴随着强大的需求,即时编译器在将来也会更加强大。 https://www.zhihu.com/question/19672491
优化高并发之协程
现在的操作系统都是支持多任务的,多任务可通过多进程或多线程的方式去实现,进程和线程的对比就不在这里说了,在多任务的调度上操作系统采取抢占式和协作式两种方式,抢占式是指操作系统给每个任务一定的执行时间片,在到达这个时间片后如任务仍然未释放对CPU的占用,那么操作系统将强制释放,这是目前多数操作系统采取的方式;协作式是指操作系统按照任务的顺序来分配CPU,每个任务执行过程中除非其主动释放,否则将一直占据CPU,这种方式非常值得注意的是一旦有任务占据CPU不放,会导致其他任务”饿死”的现象,因此操作系统确实不太适合采用这种方式。 说完操作系统多任务的调度方式后,来看看通常程序是如何实现支持高并发的,一种就是典型的基于操作系统提供的多进程或多线程机制,每个任务占据一个进程或一个线程,当任务中有IO等待等动作时,则将进程或线程放入待调度队列中,这种方式是目前大多数程序采取的方式,这种方式的坏处在于如想支持高的并发量,就不得不创建很多的进程或线程,而进程和线程都是要消耗不少系统资源的,另外一方面,进程或线程创建太多后,操作系统需要花费很多的时间在进程或线程的切换上,切换动作需要做状态保持和恢复,这也会消耗掉很多的系统资源;另外一种方式则是每个任务不完全占据一个进程或线程,当任务执行过程中需要进行IO等待等动作时,任务则将其所占据的进程或线程释放,以便其他任务使用这个进程或线程,这种方式的好处在于可以减少所需要的原生的进程或线程数,并且由于操作系统不需要做进程或线程的切换,而是自行来实现任务的切换,其成本会较操作系统切换低,这种方式也就是本文的重点,Coroutine方式,又称协程方式,这种方式在目前的大多数语言中都有支持。 各种语言在实现Coroutine方式的支持时,多数都采用了Actor Model来实现,Actor Model简单来说就是每个任务就是一个Actor,Actor之间通过消息传递的方式来进行交互,而不采用共享的方式,Actor可以看做是一个轻量级的进程或线程,通常在一台4G内存的机器上,创建几十万个Actor是毫无问题的,Actor支持Continuations,即对于如下代码: ``` Actor act方法 进行一些处理 创建并执行另外一个Actor 通过消息box阻塞获取另一个Actor执行的结果 继续基于这个结果进行一些处理 ``` 在支持Continuations的情况下,可以做到消息box阻塞时并不是进程或线程级的阻塞,而只是Actor本身的阻塞,并且在阻塞时可将所占据的进程或线程释放给其他Actor使用,Actor Model实现最典型的就是erLang了。 对于Java应用而言,传统方式下为了支持高并发,由于一个线程只能用于处理一个请求,即使是线程中其实有很多IO中断、锁等待也同样如此,因此通常的做法是通过启动很多的线程来支撑高并发,但当线程过多时,就造成了CPU需要消耗不少的时间在线程的切换上,从而出现瓶颈,按照上面对Coroutine的描述,Coroutine的方式理论上而言能够大幅度的提升Java应用所能支撑的并发量。 Java尚不能从语言层次上支持Coroutine,在java中使用协程,可以使用协程框架,Kilim就是一种比较流行的协程框架。 Kilim是由剑桥的两位博士开发的一个用于在Java中使用Coroutine的框架,Kilim基于Java语法。( 具体了解可看这个,http://www.malhar.net/sriram/kilim/ 或 http://www.ibm.com/developerworks/cn/java/j-javadev2-7.html) 经测试,当线程数增加时,系统时耗激增。由于操作系统本地线程数量的限制,无法正常运行线程数8000和10000的测试代码。而使用协程的方式,其增长曲线显得十分平缓。使用协程,可以让系统以更低的成本,支持更高的并行度。 总结而言,采用Coroutine方式可以很好的绕开需要启动太多线程来支撑高并发出现的瓶颈,提高Java应用所能支撑的并发量,但在开发模式上也会带来变化,并且需要特别注意不能造成线程被阻塞的现象,从开发易用和透明迁移现有Java应用两个角度而言目前Coroutine方式还有很多不足,但相信随着越来越多的人在Java中使用Coroutine,其易用性必然是能够得到提升的。 相关资料: http://en.wikipedia.org/wiki/Computer_multitasking http://en.wikipedia.org/wiki/Coroutine http://en.wikipedia.org/wiki/Actor_model http://en.wikipedia.org/wiki/Continuation http://lamp.epfl.ch/~phaller/doc/haller07coord.pdf http://www.scala-lang.org/sites/default/files/odersky/jmlc06.pdf...
Java 虚拟机有自己完善的硬件架构, 如处理器、堆栈、寄存器等,还具有相应的指令系统。JVM 屏蔽了与具体操作系统平台相关的信息,使得 Java 程序只需生成在 Java 虚拟机上运行的目标代码 (字节码), 就可以在多种平台上不加修改地运行。Java 虚拟机在执行字节码时,实际上最终还是把字节码解释成具体平台上的机器指令执行。 注意:本文仅针对 JDK7、HotSPOT Java 虚拟机,对于 JDK8 引入的 JVM 新特性及其他 Java 虚拟机,本文不予关注。 我们以一个例子开始这篇文章。假设你是一个普通的 Java 对象,你出生在 Eden 区,在 Eden 区有许多和你差不多的小兄弟、小姐妹,可以把 Eden 区当成幼儿园,在这个幼儿园里大家玩了很长时间。Eden...
Redis为单进程单线程模式,采用队列模式将并发访问变为串行访问。Redis本身没有锁的概念,Redis对于多个客户端连接并不存在竞争,但是在Jedis客户端对Redis进行并发访问时会发生连接超时、数据转换错误、阻塞、客户端关闭连接等问题,这些问题均是由于客户端连接混乱造成。对此有2种解决方法: 1.客户端角度,为保证每个客户端间正常有序与Redis进行通信,对连接进行池化,同时对客户端读写Redis操作采用内部锁synchronized。 2.服务器角度,利用setnx实现锁。 对于第一种,需要应用程序自己处理资源的同步,可以使用的方法比较通俗,可以使用synchronized也可以使用lock;第二种需要用到Redis的setnx命令,但是需要注意一些问题。 SETNX命令(SET if Not eXists) 语法: SETNX key value 功能: 将 key 的值设为 value ,当且仅当 key 不存在;若给定的 key 已经存在,则 SETNX 不做任何动作。 时间复杂度: O(1) 返回值: 设置成功,返回 1 。...
你是一个普通的 Java 对象,你出生在 Eden 区,在 Eden 区有许多和你差不多的小兄弟、小姐妹,可以把 Eden 区当成幼儿园,在这个幼儿园里大家玩了很长时间。Eden 区不能无休止地放你们在里面,所以当年纪稍大,你就要被送到学校去上学,这里假设从小学到高中都称为 Survivor 区。开始的时候你在 Survivor 区里面划分出来的的“From”区,读到高年级了,就进了 Survivor 区的“To”区,中间由于学习成绩不稳定,还经常来回折腾。直到你 18 岁的时候,高中毕业了,该去社会上闯闯了。于是你就去了年老代,年老代里面人也很多。在年老代里,你生活了 20 年 (每次 GC 加一岁),最后寿终正寝,被 GC 回收。有一点没有提,你在年老代遇到了一个同学,他的名字叫爱德华 (慕光之城里的帅哥吸血鬼),他以及他的家族永远不会死,那么他们就生活在永生代。