精华内容
下载资源
问答
  • 对于解决网络瓶颈问题,依靠增加链路吞吐量、配置端口信道或者整合服务质量等技术,但也有更多额外的技巧来更好解决瓶颈问题,下面就详情来看看了解下
  • 摘要—针对运筹学中的瓶颈分配问题,提出了一种基于成本矩阵变换的矩阵消除方法,并通过实例分析证明了该算法的有效性,并且解决方案是最优的子结构。通过比较,该方法比其他方法更有效。
  • 事实上,当很难获得利润的时候,解决存储I/O性能瓶颈在经济疲软时变得更加重要。  对于数据中心来说,虚拟环境下的存储I/O瓶颈是一个不断加重且长期存在的问题,因为存储控制器和头设备会被虚拟机发出的大量I/O请求...
  • 为了解决瓶颈节点,结合数据压缩和数据融合技术以减少传向汇聚节点的数据量,在汇聚节点以上使用高速网络,当数据量超出汇聚节点的处理能力时,在汇聚节点采用根据兴趣或数据的优先级对数据进行选择性传输,给出了...
  • 这个会议纪要是描述化工行业工艺装置的存在问题的纪要,很值得其它行业学习。
  • 电动汽车发展的瓶颈问题解决对策探析.pdf
  • HPB 如何解决区块链性能瓶颈问题_李琼@HPB芯链.pdf
  • 电动汽车发展前景及急需解决瓶颈技术问题.pdf
  • 事实上,当很难获得利润的时候,解决存储I/O性能瓶颈在经济疲软时变得更加重要。  对于数据中心来说,虚拟环境下的存储I/O瓶颈是一个不断加重且长期存在的问题,因为存储控制器和头设备会被虚拟机发出的大量I/O请求...
  • 特别是针对网络广播实现中的技术难点,提出了较为可行而又新颖的解决措施,如针对网络广播中的带宽瓶颈问题,本文提出了“改进压缩编码方法”、“采用镜像服务器”、“采用边缘服务器”、“采用缓冲服务器”等措施,这些...
  • 1、数据分析之数据准备瓶颈:OLAP 我们知道从上个世纪90年代,甚包括80年代末,OLAP就已经被很好地使用了。但是我们知道企业的数据和运营的过程,是个持续动态变化的过程,它需要在第时间交给业务部门做数据分析,而...

    1、数据分析之数据准备瓶颈:OLAP

    我们知道从上个世纪90年代,甚包括80年代末,OLAP就已经被很好地使用了。但是我们知道企业的数据和运营的过程,是个持续动态变化的过程,它需要在第时间交给业务部门做数据分析,而OLAP做不到这点。旦有个数据分析的变化,我们需要交给IT部门去重新构建OLAP。所以如果这个瓶颈不打掉,企业的数据化运营的链条是不通畅的,并且业务流程会很缓慢,同时企业的运营效率和竞争能力也会大打折扣。

    2、大数据分析之找到答案瓶颈:静态报告

    如果我们采用邮件的形式沟通,假设今天发出去,天才有回复,那这天就浪费了。静态报告就跟邮件样,我们需要的是个及时交互的过程,对数据进行分析、发掘它的价值。假如看到报告后,我们就发现了个问题,然后可能就会去问个问题。比如华南的几个业务增长发生了变化,上个季度可能是100%的增长,到这个季度增长降成了10%,这个时候我们就会去问为什么,但是静态报告是不能告诉我们答案的。这个问题只能再交给IT部门重新计算遍,再给出张静态报告。如果不打掉这个窘迫,会给企业数据化运营带来很大的挑战。

    3、大数据分析之分析流程瓶颈:IT部门

    个企业里面有非常多的部门,假如有制造、市场、设计、人事、财务等部门。当这些部门有数据分析的需求时,他们都会递交给IT部门,然后IT部门的加班非常严重,他们疲于应付,但是这样做出的结果还非常不好,大家对IT部门的诟病都很深。比如做中秋节的策划,这个促销策划需要些数据分析的报告来支撑。但是IT部门很可能在中秋节之前,还没有把报告交给市场部门,这会给企业的营销带来好大的不便。

    4、大数据分析之厂商瓶颈:缺乏高质量的本土厂商

    我们认为在国内缺乏高质量的本土厂商。以前大家在聊大数据分析这件事情时,很可能会说SAP、IBM等等,却没有家真的做得很棒的本土厂商出现。也有些本土大数据分析厂商,往往以非常低的价格和比较差的服务去做些低端的市场。

    我们知道其实在目前的中国,已经有非常多的好的企业,在各自的行业崛起。以前我们买个电视机,可能要买东芝,后来我们可以买海尔。以前买空调需要买三菱,现在我们要买美的或者格力。在各个行业都发生了巨大的改变,有非常多的本土厂商在崛起,但是大数据分析这个领域,我们认为是没有的。所以这是我们非常大的个责任,希望可以和诸位起深入有效地合作,去改变这个现状,让本土的厂商可以提供已有的服务和产品,帮助大家做好大数据分析的支撑和服务的工作。

    人工智能、大数据、云计算和物联网的未来发展值得重视,均为前沿产业,多智时代专注于人工智能和大数据的入门和科谱,在此为你推荐几篇优质好文:
    构建一个企业的大数据分析平台 ,主要分为哪几步?
    http://www.duozhishidai.com/article-8017-1.html
    数据科学,数据分析和机器学习之间,有什么本质区别?
    http://www.duozhishidai.com/article-7892-1.html
    数据分析是什么,如何完善数据分析知识体系
    http://www.duozhishidai.com/article-7743-1.html


    多智时代-人工智能大数据学习入门网站|人工智能、大数据、物联网云计算的学习交流网站

    多智时代-人工智能大数据学习入门网站|人工智能、大数据、云计算、物联网的学习服务的好平台
    展开全文
  • 解决数据库高并发访问瓶颈问题

    万次阅读 2017-09-04 17:33:24
    分表能够解决单表数据量过大带来的查询效率下降的问题,但是却无法给数据库的并发处理能力带来质的提升。面对高并发的读写访问,当数据库master服务器无法承载写操作压力时,不管如何扩展Slave服务器都是没有意义的...

    一、缓存式的Web应用程序架构:

    在Web层和db层之间加一层cache层,主要目的:减少数据库读取负担,提高数据读取速度。cache存取的媒介是内存,可以考虑采用分布式的cache层,这样更容易破除内存容量的限制,同时增加了灵活性。


    二、实现MySQL数据库异步查询实现:

    通常情况下在PHP中MySQL查询是串行的,如果能实现MySQL查询的异步化,就能实现多条SQL语句同时执行,这样就能大大地缩短MySQL查询的耗时,提高数据库查询的效率。目前MySQL的异步查询只在MySQLi扩展提供,查询方法分别是:

    1、使用MYSQLI_ASYNC模式执行mysqli::query

    2、获取异步查询结果:mysqli::reap_async_query

    使用mysql异步查询,需要使用mysqlnd作为PHP的MySQL数据库驱动。

    使用MySQL异步查询,因为需要给所有查询都创建一个新的连接,而MySQL服务端会为每个连接创建一个单独的线程进行处理,如果创建的线程过多,则会造成线程切换引起系统负载过高。Swoole中的异步MySQL其原理是通过MYSQLI_ASYNC模式查询,然后获取mysql连接的socket,加入到epoll事件循环中,当数据库返回结果时会回调指定函数,这个过程是完全异步非阻塞的。


    三、MySQL主从读写分离:

    当数据库的写压力增加,cache层(如Memcached)只能缓解数据库的读取压力。读写集中在一个数据库上让数据库不堪重负。使用主从复制技术(master-slave模式)来达到读写分离,以提高读写性能和读库的可扩展性。读写分离就是只在主服务器上写,只在从服务器上读,基本原理是让主数据库处理事务性查询,而从数据库处理select查询,数据库复制被用于把事务性查询(增删改)导致的改变更新同步到集群中的从数据库。

    MySQL读写分离提升系统性能:

    1、主从只负责各自的读和写,极大程度缓解X锁和S锁争用。

    2、slave可以配置MyISAM引擎,提升查询性能以及节约系统开销。

    3、master直接写是并发的,slave通过主库发送来的binlog恢复数据是异步的。

    4、slave可以单独设置一些参数来提升其读的性能。

    5、增加冗余,提高可用性。

    实现主从分离可以使用MySQL中间件如:Atlas


    四、分表分库:

    在cache层的高速缓存,MySQL的主从复制,读写分离的基础上,这时MySQL主库的写压力开始出现瓶颈,而数据量的持续猛增,由于MyISAM使用表锁,在高并发下会出现严重的锁问题,大量的高并发MySQL应用开始使用InnoDB引擎代替MyISAM。采用Master-Slave复制模式的MySQL架构,只能对数据库的读进行扩展,而对数据的写操作还是集中在Master上。这时需要对数据库的吞吐能力进一步地扩展,以满足高并发访问与海量数据存储的需求。

    对于访问极为频繁且数据量巨大的单表来说,首先要做的是减少单表的记录条数,以便减少数据查询所需的时间,提高数据库的吞吐,这就是所谓的分表【水平拆分】。在分表之前,首先需要选择适当的分表策略,使得数据能够较为均衡地分布到多张表中,并且不影响正常的查询。

    分表能够解决单表数据量过大带来的查询效率下降的问题,但是却无法给数据库的并发处理能力带来质的提升。面对高并发的读写访问,当数据库master服务器无法承载写操作压力时,不管如何扩展Slave服务器都是没有意义的,对数据库进行拆分,从而提高数据库写入能力,即分库【垂直拆分】

    分库分表的理由策略如下:

    1、中间变量=user_id % ( 库数量 * 每个库的表数量 )

    2、库=取整(中间变量 / 每个库的表数量)

    3、表=中间变量 % 每个库的表数量

    数据库经过业务拆分及分库分表,虽然查询性能和并发处理能力提高了。但是原本跨表的事务上升为分布式事务;由于记录被切分到不同的库和不同的表中,难以进行多表关联查询,并且不能不指定路由字段对数据进行查询。且分库分表后需要进一步对系统进行扩容(路由策略变更)将变得非常不方便,需要重新进行数据迁移。

    展开全文
  • 放大器电路的大信号带宽遇瓶颈:如何解决压摆率问题
  • 本书主要讲解了架构知识,不仅仅是架构知识,更多的是互联网场景下大型网站架构演变过程中核心技术难题的解决方案。
  • 甚至会出现拒绝服务的问题,第一时间想到是机器性能问题,无法满足并发如此大的场景,需要进行扩容或者服务限流。经过扩容之后平稳了一个多月之后,又一次大量请求打进来的时候出现了此问题。这时才意识到开始从各个...

    事故发现

    服务在生产环境中,由于同一时间段请求量过大,导致服务响应速度急剧下降。甚至会出现拒绝服务的问题,第一时间想到是机器性能问题,无法满足并发如此大的场景,需要进行扩容或者服务限流。经过扩容之后平稳了一个多月之后,又一次大量请求打进来的时候出现了此问题。这时才意识到开始从各个角度去排查问题。

    事故排查过程

    一个系统的吞吐量(承压能力)与request对CPU的消耗、外部接口、IO等等紧密关联。单个reqeust 对CPU消耗越高,外部系统接口、IO影响速度越慢,系统吞吐能力越低,反之越高。所以对于性能方面影响,需要排查的原因比较广。

    首先通过top排查机器情况,并未发现太多问题。然后又结合业务代码、第三方接口请求和数据库请求进行排查,依旧没能找到突破点。

    此时通过观察日志发现,日志的打印间隔竟然有高达2秒的,而且比例还不少,这明显是不正常的。

    log4j采用buffer进行输出,怀疑是否log4j中buffer容量配置问题。于是增加buffer大小,进行压力测试,buffer增加到了8M,发现并没有什么实际的效果,于是开始怀疑同步性能低。

    为了验证是否同步性能问题导致的,故将该服务的日志改为异步日志,发现qps得到了数十倍的增长,采用异步之后,问题已经觉得基本解决了。但是回过头来想,同步日志到底是什么问题导致性能会如此低下呢?还有就是其他的使用同步日志的服务,为什么没有出现这个问题?

    同步日志性能探究

    对于服务线程响应变慢,我想到了用jstack直接去观察服务的线程堆栈信息,发现大量线程的堆栈类似如下:

    "pool-1-thread-190" prio=10 tid=0x00002b853809d800 nid=0xc01 waiting for monitor entry [0x00002b84b85d5000]
       java.lang.Thread.State: BLOCKED (on object monitor)
        at org.apache.log4j.Category.callAppenders(Category.java:204)
        - waiting to lock <0x00000007880579e8> (a org.apache.log4j.spi.RootLogger)
        at org.apache.log4j.Category.forcedLog(Category.java:391)
        at org.apache.log4j.Category.info(Category.java:666)
        at com.jlpay.commons.rpc.thrift.server.Dispatcher.invoke(Dispatcher.java:38)
        at com.jlpay.commons.rpc.thrift.server.RpcAdapterImpl.Invoke(RpcAdapterImpl.java:32)
        at com.jlpay.commons.rpc.thrift.server.RpcAdapter$Processor$Invoke.getResult(RpcAdapter.java:175)
        at com.jlpay.commons.rpc.thrift.server.RpcAdapter$Processor$Invoke.getResult(RpcAdapter.java:160)
        at org.apache.thrift.ProcessFunction.process(ProcessFunction.java:39)
        at org.apache.thrift.TBaseProcessor.process(TBaseProcessor.java:39)
        at org.apache.thrift.server.AbstractNonblockingServer$FrameBuffer.invoke(AbstractNonblockingServer.java:518)
        at org.apache.thrift.server.Invocation.run(Invocation.java:18)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
        at java.lang.Thread.run(Thread.java:724)
    

    大量线程阻塞,等待某个锁,但是这个锁被以下线程持有:

    "pool-1-thread-102" prio=10 tid=0x00002b8538053800 nid=0xba9 runnable [0x00002b84b2f71000]
       java.lang.Thread.State: RUNNABLE
        at java.text.DateFormat.format(DateFormat.java:336)
        at org.apache.log4j.helpers.PatternParser$DatePatternConverter.convert(PatternParser.java:443)
        at org.apache.log4j.helpers.PatternConverter.format(PatternConverter.java:65)
        at org.apache.log4j.PatternLayout.format(PatternLayout.java:506)
        at org.apache.log4j.WriterAppender.subAppend(WriterAppender.java:310)
        at org.apache.log4j.WriterAppender.append(WriterAppender.java:162)
        at org.apache.log4j.AppenderSkeleton.doAppend(AppenderSkeleton.java:251)
        - locked <0x0000000788057650> (a org.apache.log4j.ConsoleAppender)
        at org.apache.log4j.helpers.AppenderAttachableImpl.appendLoopOnAppenders(AppenderAttachableImpl.java:66)
        at org.apache.log4j.Category.callAppenders(Category.java:206)
        - locked <0x00000007880579e8> (a org.apache.log4j.spi.RootLogger)
    

    恍然大悟,同步日志的速度慢是因为大量线程阻塞等待获取锁,再写日志。

    简单看了下logger输出日志的过程源码,发现有很多逻辑都在加锁的场景下处理的。高并发下,大量写日志请求,这个问题就会暴露出来。

    而且写日志操作相对来说还是比较慢的,高并发下会导致请求的平均处理时间高于正常情况下的处理时间;但是处理时间也不会大幅度增加到引起客户端请求超时的地步。因为相比与纯粹的cpu处理操作,写日志是一个慢操作,但是也不是肉眼能见的慢,写完日志的线程最终会释放锁,其他线程获得锁。

    思考

    还存在一个问题,为什么其他的同步日志服务,在业务量和请求量相似的情况下,没有暴露出该问题呢?对比了一下对应的日志配置,发现主要在打印格式上的区别:

    
    //出问题服务:
    %d{yyyy/MM/dd HH:mm:ss.SSS}[traceId: %X{trace_id}] %t [%p] %C{1} (%F:%M:%L) %msg%n
    
    //未出问题的服务
    [%d{yy-MM-dd.HH:mm:ss.SSS}] [%thread]  [%-5p %-22c{0} -] %m%n
    
    

    专门看了下log4j官网的信息(http://logging.apache.org/log4j/2.x/performance.html#asyncLoggingWithLocation

    在这里插入图片描述
    大概也就是说日志格式使用这些参数的使用会导致性能的急剧下降
    C or $class, %F or %file, %l or %location, %L or %line, %M or %method
    大概下降30-100倍左右,这才找到真正的原因,原来同步和异步的性能影响是一部分,本身日志格式的配置也是存在问题的。

    较为影响性能的日志输出参数

    %C     - 调用者的类名(速度慢,不推荐使用);
    %F     - 调用者的文件名(速度极慢,不推荐使用)
    %l     - 调用者的函数名、文件名、行号(速度极其极其慢,不推荐使用)
    %L     - 调用者的行号(速度极慢,不推荐使用)
    %M     - 调用者的函数名(速度极慢,不推荐使用)
    

    发现这几个性能比较低下的参数,做的都是定位类的工作,都是LocationInfo类下的成员。
    LocationInfo.java

    public class LocationInfo implements java.io.Serializable {
    
      /**
         Caller's line number.
      */
      transient String lineNumber;
      /**
         Caller's file name.
      */
      transient String fileName;
      /**
         Caller's fully qualified class name.
      */
      transient String className;
      /**
         Caller's method name.
      */
      transient String methodName;
      /**
         All available caller information, in the format
         <code>fully.qualified.classname.of.caller.methodName(Filename.java:line)</code>
        */
      public String fullInfo;
    
    
    //...
    }
    

    再通过LogEvent.getLocationInformation()的源码发现,log4j为了拿到函数名称和行号信息,利用了异常机制,首先抛出一个异常,之后捕获异常并打印出异常信息的堆栈内容,再从堆栈内容中解析出行号。( jvm对异常的处理损耗是不可忽略的,这是性能慢的原因之一

    public class LogEvent implements java.io.Serializable {
        
        public LocationInfo getLocationInformation() {
        if(locationInfo == null) {
          locationInfo = new LocationInfo(new Throwable(), fqnOfCategoryClass);
        }
        return locationInfo;
      }
    
    }
    

    再看看LocationInfo对应的构造方法部分,需要通过同步锁去获取异常栈内的内容,可见这是操作是有多消耗性能:

    
     public LocationInfo(Throwable t, String fqnOfCallingClass) {
          
          //...
    
          synchronized(sw) {
            t.printStackTrace(pw);
            s = sw.toString();
            sw.getBuffer().setLength(0);
         }
          //System.out.println("s is ["+s+"].");
          int ibegin, iend;
    
          
          ibegin = s.lastIndexOf(fqnOfCallingClass);
    
          //...
    
    

    问题基本明了了。

    再次压测

    将服务中日志格式中的(%F:%M:%L)剔除,再进行压测。QPS上升至2000+,果然不踩坑就很难注意到这中小配置,有这么大的性能影响,算是给自己上了一课。

    展开全文
  • memcache解决高并发的数据库瓶颈问题

    千次阅读 2011-05-03 18:35:00
    高并发面临的问题  对于高并发高访问的Web应用程序来说,数据库存取瓶颈一直是个令人头疼的问题。特别当你的程序架构还是建立在单数据库模式,而一个数据池连接数峰值已经达到500的时候,那你的程序运行...

    高并发面临的问题

      对于高并发高访问的Web应用程序来说,数据库存取瓶颈一直是个令人头疼的问题。特别当你的程序架构还是建立在单数据库模式,而一个数据池连接数峰值已经达到500的时候,那你的程序运行离崩溃的边缘也不远了。很多小网站的开发人员一开始都将注意力放在了产品需求设计上,缺忽视了程序整体性能,可扩展性等方面的考虑,结果眼看着访问量一天天网上爬,可突然发现有一天网站因为访问量过大而崩溃了,到时候哭都来不及。所以我们一定要未雨绸缪,在数据库还没罢工前,想方设法给它减负,这也是这篇文章的主要议题。

      大家都知道,当有一个request过来后,web服务器交给app服务器,app处理并从db中存取相关数据,但db存取的花费是相当高昂的。特别是每次都取相同的数据,等于是让数据库每次都在做高耗费的无用功,数据库如果会说话,肯定会发牢骚,你都问了这么多遍了,难道还记不住吗?是啊,如果app拿到第一次数据并存到内存里,下次读取时直接从内存里读取,而不用麻烦数据库,这样不就给数据库减负了?而且从内存取数据必然要比从数据库媒介取快很多倍,反而提升了应用程序的性能。

    因此,我们可以在web/app层与db层之间加一层cache层,主要目的:1. 减少数据库读取负担;2. 提高数据读取速度。而且,cache存取的媒介是内存,而一台服务器的内存容量一般都是有限制的,不像硬盘容量可以做到TB级别。所以,可以考虑采用分布式的cache层,这样更易于破除内存容量的限制,同时又增加了灵活性。

    Memcached 介绍

      Memcached是开源的分布式cache系统,现在很多的大型web应用程序包括facebook,youtube,wikipedia,yahoo等等都在使用memcached来支持他们每天数亿级的页面访问。通过把cache层与他们的web架构集成,他们的应用程序在提高了性能的同时,还大大降低了数据库的负载。
    具体的memcached资料大家可以直接从它的官方网站[1]上得到。这里我就简单给大家介绍一下memcached的工作原理:

      Memcached处理的原子是每一个(key,value)对(以下简称kv对),key会通过一个hash算法转化成hash-key,便于查找、对比以及做到尽可能的散列。同时,memcached用的是一个二级散列,通过一张大hash表来维护。

      Memcached有两个核心组件组成:服务端(ms)和客户端(mc),在一个memcached的查询中,mc先通过计算key的hash值来确定kv对所处在的ms位置。当ms确定后,客户端就会发送一个查询请求给对应的ms,让它来查找确切的数据。因为这之间没有交互以及多播协议,所以memcached交互带给网络的影响是最小化的。

    举例说明:考虑以下这个场景,有三个mc分别是X,Y,Z,还有三个ms分别是A,B,C:

    设置kv对
    X想设置key=”foo”,value=”seattle”
    X拿到ms列表,并对key做hash转化,根据hash值确定kv对所存的ms位置
    B被选中了
    X连接上B,B收到请求,把(key=”foo”,value=”seattle”)存了起来

    获取kv对
    Z想得到key=”foo”的value
    Z用相同的hash算法算出hash值,并确定key=”foo”的值存在B上
    Z连接上B,并从B那边得到value=”seattle”
    其他任何从X,Y,Z的想得到key=”foo”的值的请求都会发向B

    Memcached服务器(ms)

    内存分配

      默认情况下,ms是用一个内置的叫“块分配器”的组件来分配内存的。舍弃c++标准的malloc/free的内存分配,而采用块分配器的主要目的是为了避免内存碎片,否则操作系统要花费更多时间来查找这些逻辑上连续的内存块(实际上是断开的)。用了块分配器,ms会轮流的对内存进行大块的分配,并不断重用。当然由于块的大小各不相同,当数据大小和块大小不太相符的情况下,还是有可能导致内存的浪费。

      同时,ms对key和data都有相应的限制,key的长度不能超过250字节,data也不能超过块大小的限制 --- 1MB。因为mc所使用的hash算法,并不会考虑到每个ms的内存大小。理论上mc会分配概率上等量的kv对给每个ms,这样如果每个ms的内存都不太一样,那可能会导致内存使用率的降低。所以一种替代的解决方案是,根据每个ms的内存大小,找出他们的最大公约数,然后在每个ms上开n个容量=最大公约数的instance,这样就等于拥有了多个容量大小一样的子ms,从而提供整体的内存使用率。

    缓存策略

      当ms的hash表满了之后,新的插入数据会替代老的数据,更新的策略是LRU(最近最少使用),以及每个kv对的有效时限。Kv对存储有效时限是在mc端由app设置并作为参数传给ms的。同时ms采用是偷懒替代法,ms不会开额外的进程来实时监测过时的kv对并删除,而是当且仅当,新来一个插入的数据,而此时又没有多余的空间放了,才会进行清除动作。

    缓存数据库查询

     

    现在memcached最流行的一种使用方式是缓存数据库查询,下面举一个简单例子说明:

    App需要得到userid=xxx的用户信息,对应的查询语句类似:

    “SELECT * FROM users WHERE userid = xxx”

    App先去问cache,有没有“user:userid”(key定义可预先定义约束好)的数据,如果有,返回数据;如果没有,App会从数据库中读取数据,并调用cache的add函数,把数据加入cache中。

    当取的数据需要更新,app会调用cache的update函数,来保持数据库与cache的数据同步。

    从上面的例子我们也可以发现,一旦数据库的数据发现变化,我们一定要及时更新cache中的数据,来保证app读到的是同步的正确数据。当然我们可以通过定时器方式记录下cache中数据的失效时间,时间一过就会激发事件对cache进行更新,但这之间总会有时间上的延迟,导致app可能从cache读到脏数据,这也被称为狗洞问题。(以后我会专门描述研究这个问题)

    数据冗余与故障预防

      从设计角度上,memcached是没有数据冗余环节的,它本身就是一个大规模的高性能cache层,加入数据冗余所能带来的只有设计的复杂性和提高系统的开支。当一个ms上丢失了数据之后,app还是可以从数据库中取得数据。不过更谨慎的做法是在某些ms不能正常工作时,提供额外的ms来支持cache,这样就不会因为app从cache中取不到数据而一下子给数据库带来过大的负载。

      同时为了减少某台ms故障所带来的影响,可以使用“热备份”方案,就是用一台新的ms来取代有问题的ms,当然新的ms还是要用原来ms的IP地址,大不了数据重新装载一遍。

      另外一种方式,就是提高你ms的节点数,然后mc会实时侦查每个节点的状态,如果发现某个节点长时间没有响应,就会从mc的可用server列表里删除,并对server节点进行重新hash定位。当然这样也会造成的问题是,原本key存储在B上,变成存储在C上了。所以此方案本身也有其弱点,最好能和“热备份”方案结合使用,就可以使故障造成的影响最小化。

    Memcached客户端(mc)

      Memcached客户端有各种语言的版本供大家使用,包括java,c,php,.net等等,具体可参见memcached api page[2]。大家可以根据自己项目的需要,选择合适的客户端来集成。

    缓存式的Web应用程序架构
      有了缓存的支持,我们可以在传统的app层和db层之间加入cache层,每个app服务器都可以绑定一个mc,每次数据的读取都可以从ms中取得,如果没有,再从db层读取。而当数据要进行更新时,除了要发送update的sql给db层,同时也要将更新的数据发给mc,让mc去更新ms中的数据。

    假设今后我们的数据库可以和ms进行通讯了,那可以将更新的任务统一交给db层,每次数据库更新数据的同时会自动去更新ms中的数据,这样就可以进一步减少app层的逻辑复杂度。如下图:

    不过每次我们如果没有从cache读到数据,都不得不麻烦数据库。为了最小化数据库的负载压力,我们可以部署数据库复写,用slave数据库来完成读取操作,而master数据库永远只负责三件事:1.更新数据;2.同步slave数据库;3.更新cache。如下图:

    以上这些缓存式web架构在实际应用中被证明是能有效并能极大地降低数据库的负载同时又能提高web的运行性能。当然这些架构还可以根据具体的应用环境进行变种,以达到不同硬件条件下性能的最优化。

    未来的憧憬

      Memcached的出现可以说是革命性的,第一次让我们意识到可以用内存作为存储媒介来大规模的缓存数据以提高程序的性能。不过它毕竟还是比较新的东西,还需要很多有待优化和改进的地方,例如:
    如何利用memcached实现cache数据库,让数据库跑在内存上。这方面,tangent software 开发的memcached_engine[3]已经做了不少工作,不过现在的版本还只是处于实验室阶段。如何能方便有效的进行批量key清理。因为现在key是散列在不同的server上的,所以对某类key进行大批量清理是很麻烦的。因为memcached本身是一个大hash表,是不具备key的检索功能的。所以memcached是压根不知道某一类的key到底存了多少个,都存在哪些server上。而这类功能在实际应用中却是经常用到。

     

    展开全文
  • 随着器件工作频率越来越高,高速PCB设计所面临的信号完整性等问题成为传统设计的一个瓶颈,工程师在设计出完整的解决方案上面临越来越大的挑战。尽管有关的高速仿真工具和互连工具可以帮助设计设计师解决部分难题,...
  • 本文应用计算机软件及计算机网络,研制出能解决体育数据处理过程中出现的“瓶颈问题的方法,旨在提高现阶段大型体质检测和大学体育中的大数据量的录入效率,解决当前实施《学生体质健康标准》及各类大型体育数据...
  • Java访问数据库的速度瓶颈问题的分析及解决
  • 电子商务通常是指是在全球各地广泛的商业贸易活动中,在因特网开放的网络环境下,基于浏览器/服务器应用方式,买卖... 一、我国电子商务发展当前存在的瓶颈问题  1.电脑网络普及率低,缺乏基础条件  电子商务...
  • 学编程遇到瓶颈问题

    千次阅读 2013-10-03 17:57:12
    每个人学编程都会遇到瓶颈问题,我也遇到过,我是怎么解决的,我的一些个人看法
  • 利用固态硬盘解决存储瓶颈.pdf
  • 所以,这是一种特别有哲理的解决方案: 与其人多,但是好多人闲着;还不如一个人玩命,往死里干活儿。 3.事件驱动 在Node中,客户端请求建立连接,提交数据等行为,会触发相应的事件。在Node中,在一个时刻,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 271,300
精华内容 108,520
关键字:

怎么解决瓶颈问题