在高并发量的场景下磁盘IO往往是性能的瓶颈所在,访问日志涉及到频繁的写操作,所以这部分要尽可能地优化,不然将拖累系统的整体性能。针对文件记录及数据库记录两种方式可以有以下措施提高写性能,

l 避免频繁的打开关闭文件。将日志写入文件的一般操作步骤是打开-写入-关闭,但假如在需要频繁写入日志的场景下,这种方式在性能上肯定会存在问题,因为每次打开关闭都是需要成本开销的,所以必须要想想是否有别的更好的方式,竟然问题出现在打开关闭的次数,那么解决问题思路就从这里下手,可以在第一次打开写入日志后不进行关闭操作,保持打开的状态,下一次写入则无需再次打开可直接写入。而由于实际过程中访问日志产生的量非常大,肯定不可能只往一个文件中写入数据,可能会按时间间隔每天写一个文件或按文件大小每50M写一个文件,所以在实际设计中会涉及到更换文件的操作,更换时需要把原来的文件流关闭。通过上述措施避免了文件频繁的打开关闭操作,但它同时也存在一些缺点,文件流不关闭会一直占用操作系统资源,且如果不及时关闭可能在程序运行过程中发生异常未正确处理而导致文件流未能关闭,进而将会导致内存泄漏。

l 添加缓冲区:添加缓冲区的作用简单地说应该是减少文件真实写入磁盘的次数,一般将文件写入的方式是每执行一次写入操作就把此次需要写入的数据写入磁盘介质中,而缓冲区模式则是把要写入的数据先写入内存中,当缓冲区内存量达到一定程度才写入磁盘,所以添加了缓冲区的文件操作并非每次写入都是存储介质中,缓冲区对于IO操作是一个十分重要的概念,缓冲区具体的实现可以参考我前面相关的章节,当然jdk已经提供了相关的缓冲类并不用我们重复制造轮子。缓冲区的添加无疑提高了操作性能,但它同样存在缺点,它无法百分之百保证所有数据都成功记录到存储介质中,可能在系统发生意外时导致缓冲区无法写入文件,而丢失的仅仅是缓冲区的数据。

l 利用“池”技术优化连接避免每次创建连接,池技术更多的是针对以数据库做为存储端的方案,即是我们最熟悉的连接池了,JDBC每次创建连接都需要很大的成本开销,如果每次写入都重新建立连接这对系统来说简直无法忍受,于是可以在系统初始化时就创建一个连接池,池内包含了很多建立好的连接,每次使用时只需往池里取出,使用完不关闭连接而是把连接重新放回池里即可。此种方式的好处显而易见,操作性能大大地提高,而如果真要说有哪些缺点的话估计只能说连接池需要占用一些操作系统资源,即使没有被使用。但对于现在的机器这点成本消耗基本可以忽略不计。

l 优化锁竞争,首先,在一个高并发的场景中日志的写入肯定是多线程的,多线程的使用在提高系统性能的作用是毋庸置疑的;其次,竟然在文件流的写入操作是多线程的,那必然涉及到锁竞争的问题,因为如果没有锁的保护文件可能被写得乱七八糟且正确性无法得到保证,所以线程一定是在写入前先尝试竞争写入锁,只有成功获取锁的线程才能执行写入操作,一旦写完就释放锁;最后,这种锁的竞争跟JDK的实现及JVM的实现相关,可能是所有竞争的线程采用自旋方式获取锁,也可能是采用线程挂起方式,对于自旋方式及挂起方式在不同场景有各自的优势,线程自旋模式可能会消耗资源,同样挂起恢复也可能会消耗资源,在实际使用中可通过性能测试比较决定使用哪种方式。在JDK的自带的并发包是先尝试自旋获取,若干次失败后进行挂起操作。

l 考虑使用非阻塞模式,所谓非阻塞(NIO)是指在进行IO操作时当执行写入操作时不等待执行结果而是直接放弃对CPU的使用,这种模式基于事件驱动,不同的事件由某一或若干线程处理,在实际中NIO模式被证实在某些场景中是性能提升的利器。它的唯一缺点估计是让你程序变得更加复杂。

使用异步IO,异步IO(AIO)是JDK1.7后提供的一种新IO模式,它主要是针对CPU的优化,是CPU级别的优化尝试,在实际中使用需要对系统使用场景做性能测试对比再决定是否进行AIO改造。

喜欢研究java的同学可以交个朋友,下面是本人的微信号:

访问日志IO性能优化的更多相关文章

  1. 性能调优之访问日志IO性能优化

    性能调优之访问日志IO性能优化   poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣,请大家咨询qq:908821 ...

  2. 按日期切割nginx访问日志--及性能优化

    先谈下我们需求,一个比较大的nginx访问日志,根据访问日期切割日志,保存在/tmp目录下. 测试机器为腾讯云机子,单核1G内存.测试日志大小80M. 不使用多线程版: #!/usr/bin/env ...

  3. log4j日志输出性能优化-缓存、异步

     转载 1.log4j已成为大型系统必不可少的一部分,log4j可以很方便的帮助我们在程序的任何位置输出所要打印的信息,便于我们对系统在调试阶段和正式运行阶段对问题分析和定位.由于日志级别的不同,对系 ...

  4. ELK Stack 日志平台性能优化

    转载自: https://mp.weixin.qq.com/s?__biz=MzAwNTM5Njk3Mw==&mid=2247487789&idx=1&sn=def0d8c2e ...

  5. MySQL数据库在IO性能优化方面的设置选择(硬件)

    提起MySQL数据库在硬件方面的优化无非是CPU.内存和IO.下面我们着重梳理一下关于磁盘I/O方面的优化. 1.磁盘冗余阵列RAID RAID(Redundant Array of Inexpens ...

  6. Linux 文件系统IO性能优化【转】

    转自:https://blog.csdn.net/doitsjz/article/details/50837569 对于LINUX SA来说,服务器性能是需要我们特别关注的,包括CPU.IO.内存等等 ...

  7. Linux 文件系统IO性能优化

    对于LINUX SA来说,服务器性能是需要我们特别关注的,包括CPU.IO.内存等等系统的优化变得至关重要,这里转载一篇非常不错的关于IO优化的文章,供大家参考和学习: 一.关于页面缓存的信息,可以用 ...

  8. 磁盘IO性能优化-实践

    RAID卡缓存策略调整 原因详解 操作实例 I/O 调度算法 文件系统journal 磁盘挂载参数 操作实例 性能数据对比 RAID卡缓存策略调整 可以将RAID卡缓存策略由No Write Cach ...

  9. OpenStack入门篇(五)之KVM性能优化及IO缓存介绍

    1.KVM的性能优化,介绍CPU,内存,IO性能优化 KVM CPU-->qemu进行模拟ring 3-->用户应用 (用户态,用户空间)ring 0-->操作系统 (内核态,内核空 ...

随机推荐

  1. C# get 、set、索引器

    get 与 set C#类的属性有公有属性(public)和私有属性(private).如果直接将一个属性声明为public,则该类的任意实例可以随意获取或修改该属性的值,很不安全..NET Fram ...

  2. 预习视频day1

    课前预习 编译型和解释型语言优缺点 python2,pyhon3的宏观(大环境下)区别 python的种类 python编码规则 变量命名规范,常量 注释 1.编译型语言:将源码一次性转化为二进制代码 ...

  3. C stat函数的用法举例(转载)

    stat函数讲解表头文件:    #include <sys/stat.h>             #include <unistd.h>定义函数:    int stat( ...

  4. Node.js Domain 模块

    Node.js Domain(域) 简化异步代码的异常处理,可以捕捉处理try catch无法捕捉的异常.引入 Domain 模块 语法格式如下: var domain = require(" ...

  5. javascript:void(0) 含义

    javascript:void(0) 含义 我们经常会使用到 javascript:void(0) 这样的代码,那么在 JavaScript 中 javascript:void(0) 代表的是什么意思 ...

  6. 这是一个测试,测试markdown语法

    [TOC] 1. chpt1 这是一段话,前面没有空格 前面有4个空格,且在编辑状态下上面没有空行 前面有4个空格,且在编辑状态下上面有一个空行. 前面按了一下tab 1.1 1.1 2 段落1 前面 ...

  7. Jeff Atwood倾情推荐——程序员必读之书

    英文版:<Code Complete 2>中文版:<代码大全(第二版)>作者:Steve McConnell译者:金戈  汤凌  陈硕  张菲出版社:电子工业出版社出版日期:2 ...

  8. Dynamics CRM REST Builder

    今天介绍个很棒的工具叫CRM REST Builder,不管是2016之前的odata查询或者现在的web api都不在话下,界面如下,选项非常丰富 这里以retrieve multiple举个例子, ...

  9. DB 查询分析器7.01 新增的保存执行结果到多个文件功能

        1      引言   中国本土程序员马根峰(CSDN专访马根峰:海量数据处理与分析大师的中国本土程序员)推出的个人作品----万能数据库查询分析器,中文版本DB 查询分析器.英文版本< ...

  10. Python descriptor

    class A: def __init__(self, name): self.name = name def __get__(self, ins, cls): print('call get') i ...