随着umc接入主机的数量越来越多,每天产生的syslog日志数量也在剧增, 之前一天产生的syslog数量才不

到1W,随着整个集团的网络设备不端接入,导致现在每天产生的syslog数量大概在180w左右,而这些syslog对

网络和PE同学排查线上网络设备问题又是十分重要的,他们的要求是可以提供查询最近3个月的syslog, 保存一

年的syslog,在7月份的时候,针对量不多的情况,针对mysql单表做了索引,后来又做了单表备份,但是查询的

速度还是无法让人接受,后面又结合页面针对mysqlcount(*)语句做了优化: 使用count(*)语句只是在第一次查询

的时候查询一次,后面保存下来,在后面分页查询的时候,不再需要再查询总数量,即不调用count(*)之类的sql

语句,结果在翻页时,速度还是比较快,但首次查询的时候,还是非常非常慢,但这毕竟只是一个临时的解决方

案;后面结合syslog搜索的业务情况,结合各种技术参考,最终选择了使用Solr搜索引擎来解决syslog查找慢的

问题;

在做压力测试的时候,发现性能问题:在数据量不大(<1000W)的时候,用Solr搜索是比较快,但随着着

syslog数据量的不断增多,写索引和搜索的速度越来越不能让人接受,因此不得不考虑对Solr进行优化;

网上了搜了一下Solr优化的大体方案,主要从如下两个步骤来进行优化:

1.  Solr系统层面;

2.  索引字段优化;

针对Solr系统层的优化,主要有如下的方法:

1. 适当调大Solr查询缓存;

2.适当增加Solr集群的切片;

3根据查询的业务场景,适当调

整索引合并的时间,等等一系列通用的做法,针对这些修改以后,发现修改前后,对查询的性能没有本质

的提高;

针对索引字段的优化,就是针对添加到Lucence中文档各索引字段的优化, syslog索引字段主要的字段有:

id(Integer),

ip(String),

log_level(String),

log_value(String)

syslog_time(Date),

要针对这些字段优索引优化,就要首先分析索引查找的过程,要做到字段优化索引,可以从两方面考虑,

1. 减少字段索引存储量,

2. 提高查询索引比较的时间, 针对这两点,

可以毫不犹豫的考虑把String类型的字段向Integer或Long类型之类的整型字段映射转换(整型的索引存储空间

一般比字段串所占的存储索引空间要小;整型的查找比较速度比字段串类型要快,其实这也是数据库查找优化

的一个方面);基于这样的考虑,ip、log_level和syslog_time可以向相应的整型映射,各个字段具体的映射方

法如下:

1. ip 地址向整形映射,这个问题比较好解决,在计算机网络协议中,在底层是会把ip地址转换成对应的无

符号长整型,但由于java没有无符号这个概念,因此可以考虑把ip地址向整型或长整型做相互映射转换,但因为

整型比长整型占用的字节更少,因此采用整型,具体转换代码如下:

// 把ip地址转换成整形

  1.  
    public static Long ipToInteger(String ip) {
  2.  
     
  3.  
    String[] ips = StringUtils.split(ip,'.');
  4.  
    if (ips == null || ips.length < 4){
  5.  
    throw newRuntimeException("ip地址非法!");
  6.  
    }
  7.  
    Integer integerIP = 0;
  8.  
    Integer ip0= Integer.parseInteger(ips[0]);
  9.  
    Integer ip1= Integer.parseInteger(ips[1]);
  10.  
    Integer ip2= Integer.parseInteger(ips[2]);
  11.  
    Integer ip3= Integer.parseInteger(ips[3]);
  12.  
    if (ip0 > 255) {
  13.  
    throw newRuntimeException("ip0地址非法:" + ip0);
  14.  
    }
  15.  
    if (ip1 > 255) {
  16.  
    throw newRuntimeException("ip1地址非法:" + ip1);
  17.  
    }
  18.  
    if (ip2 > 255) {
  19.  
    throw newRuntimeException("ip2地址非法:" + ip2);
  20.  
    }
  21.  
    if (ip3 > 255) {
  22.  
    throw newRuntimeException("ip3地址非法:" + ip3);
  23.  
    }
  24.  
    integerIP |=( ip0 << 24) & (0xff000000);
  25.  
    integerIP |=( ip1 << 16) & (0x00ff0000);
  26.  
    integerIP |=( ip2 << 8) & (0x0000ff00);
  27.  
    integerIP |=( ip3 << 0) & (0x000000ff);
  28.  
    return integerIP ;
  29.  
    }
  1.  
    /**
  2.  
    * int类型到ip转换
  3.  
    * @param integerIP
  4.  
    * @return
  5.  
    */
  6.  
    public static String integerToIP(IntegerintegerIP) {
  7.  
     
  8.  
    String ip = "";
  9.  
    Integer ip0= (integerIP & 0xff000000) >>> 24;
  10.  
    Integer ip1= (integerIP & 0x00ff0000) >> 16 ;
  11.  
    Integer ip2= (integerIP & 0x0000ff00) >> 8;
  12.  
    Integer ip3= (integerIP & 0x000000ff) >> 0;
  13.  
    ip = ip0 + "." + ip1 +"." + ip2 + "." + ip3;
  14.  
    return ip;
  15.  
    }
 

2. log_level 只有8种值,分别是:Emergency, Alert, Critical, Error, Warning,Notice,Informational,

Debug; 这个好转换,直接按下表的方式做相互映射即可

Emergency

0

Alert

1

Critical

2

Error

3

Warning

4

Notice

5

Informational

6

Debug

7

3. 把syslog_time转换成Long类型,这个更容易,java中Date类型有一个getTime()方法

经过把这三个字段都转换成整型以后,索引插入和搜索速度都提高不少,特别是搜索速度有非常非常明显

的提升,特别是在数据量超过2亿的时间,效果更明显到此,字段优化完毕;

但此时还发现一个问题:一次查找返回的数据量太多,导致存在翻页慢的问题,例如:一次返回10W页数

据,如果一下翻到第10W页,查询的速度会非常非常慢甚至可能出现Solr集群全部宕机的情况,这是不能接受的,

因为我们页面上提供了翻到最后一面的功能, 虽然用户一般情况下不会这么做,但万一不小点错了,整个线上

Sorl集群就全部挂了,怎么办?这个问题,让我想起了mysql里的翻页的问题,下面两条SQL语句:

  • select * from umc_syslog where syslog_time between date1 and date2  order by id limit 0, 10;
  • select * from umc_syslog where syslog_time between date1 and date2  order by id limit 10000, 10;

我们知道,第一条SQL语句查询的速度非常快,第二SQL语句查询的速度非常慢,在系统压力较大的情况下,

可能会把mysql服务弄挂,根本原因在于limitstart, rows语句,mysql会在扫描时,会扫过满足结果的前start行的

记录,然后才读取len行的数据,如果start特别大,会非常慢,在高性能mysql这本书中介绍了各种解决分页问

题的优化,如延迟关联、阶递分页等,其中阶递分页可以在Solr中实现,但我们页面不允许这么做,不然早就

用Hbase来解决了,怎么办,在无解决的情况下,突然发现,Solr查询中有order by排序的问题,适当用order by

可以很好来解决limit 分页慢的问题:

假设 一个Solr查询按id 降序排序返回,假设返回10W行记录,前5W条记录可以随机分页查询到,但后面

5W条记录很难随机分页查询到,造成这个问题的原因是按id降序返回,如果适当修改一下查询语句,速度可

能会有所提高,因为Solr查询每次都会返回总的记录条数,这个总的记录条数是已知的, 记为total, 作如下处

理:如果start 小于等于 (total >> 1),则从前往后读;否则就从后往前读,然后,再把返回的结果逆序,显示

即可,伪代码如下;

  1.  
    if start <= (total >> 1)
  2.  
    query order by id desc limit start, rows;
  3.  
    else
  4.  
    calculate new start as start';
  5.  
    calculate new rows as rows';
  6.  
    query order by asc limit start', rows';
  7.  
    reverse the return data;
  8.  
    end

程序中相关代码:

  1.  
    // 是否是按id升序查询, 默认是false
  2.  
    boolean isAscend = false;
  3.  
     
  4.  
    // 升序或降序查询判断
  5.  
    if (totalCount == 0) {
  6.  
    isAscend = false;
  7.  
    } else {
  8.  
    if (start >= (totalCount >> 1) ) {
  9.  
    isAscend = true;
  10.  
    }
  11.  
    }
  12.  
     
  13.  
    if (!isAscend) {
  14.  
    realStart = start;
  15.  
    realRows = rows;
  16.  
    } else {
  17.  
    Integer count = totalCount.intValue();
  18.  
    realStart = (start + rows)>= count? 0 : (count - (start +rows));
  19.  
    realRows = (start + rows)>= count? (count - start + 1) : rows;
  20.  
    }
  21.  
    solrQuery.setStart(realStart);
  22.  
    solrQuery.setRows(realRows);
  23.  
     
  24.  
    if (!isAscend) {// id降序
  25.  
    solrQuery.setSort("id", ORDER.desc);
  26.  
    } else { // id 升序
  27.  
    solrQuery.setSort("id", ORDER.asc);
  28.  
    }
  29.  
     
  30.  
    // 逆序处理
  31.  
    if (isAscend) {
  32.  
    int size = syslogVOList.size();
  33.  
    int left = 0;
  34.  
    int right = size - 1;
  35.  
    while (left < right) {
  36.  
    SyslogVO leftSyslogVO =syslogVOList.get(left);
  37.  
    SyslogVO rightSyslogVO =syslogVOList.get(right);
  38.  
    syslogVOList.set(left, rightSyslogVO);
  39.  
    syslogVOList.set(right, leftSyslogVO);
  40.  
    left ++;
  41.  
    right --;
  42.  
    }
  43.  
    }

经过这个过程的处理之后,向后翻页查询的速度快了很多,至少不会出现宕机的现象;

查询页面如下:

在相同的条件下:

优化后Solr查询的时间:

优化前mysql的查询时间:

其实这个技巧在mysql分页查询,数据量非常大的时候也适用;

Solr优化案例分析的更多相关文章

  1. SQL性能优化案例分析

    这段时间做一个SQL性能优化的案例分析, 整理了一下过往的案例,发现一个比较有意思的,拿出来给大家分享. 这个项目是我在项目开展2期的时候才加入的, 之前一期是个金融内部信息门户, 里面有个功能是收集 ...

  2. MySQL的索引单表优化案例分析

    建表 建立本次优化案例中所需的数据库及数据表 CREATE DATABASE db0206; USE db0206; CREATE TABLE `db0206`.`article`( `id` INT ...

  3. mysql优化案例分析

    本文总结了一些工作常见的sql优化例子,虽然比较简单,但很实用,希望对大家有所帮助.sql优化一般分为两类,一类是sql本身的优化,如何走到合适的索引,如何减少排序,减少逻辑读:另一类是sql本身没有 ...

  4. 数据库sql优化总结之2-百万级数据库优化方案+案例分析

    项目背景 有三张百万级数据表 知识点表(ex_subject_point)9,316条数据 试题表(ex_question_junior)2,159,519条数据 有45个字段 知识点试题关系表(ex ...

  5. 数据库sql优化总结之1-百万级数据库优化方案+案例分析

    项目背景 有三张百万级数据表 知识点表(ex_subject_point)9,316条数据 试题表(ex_question_junior)2,159,519条数据 有45个字段 知识点试题关系表(ex ...

  6. JIT对锁的优化- 锁消除和锁粗化案例分析

    锁消除和锁粗化案例分析 锁消除 直接上代码 /** * 描述: 锁粒度演示 * @author karl * @create 2020-02-11 14:38 */ public class MySy ...

  7. 数据库优化案例——————某市中心医院HIS系统

    记得在自己学习数据库知识的时候特别喜欢看案例,因为优化的手段是容易掌握的,但是整体的优化思想是很难学会的.这也是为什么自己特别喜欢看案例,今天也开始分享自己做的优化案例. 最近一直很忙,博客产出也少的 ...

  8. 【MySQL】排序原理与案例分析

    前言 排序是数据库中的一个基本功能,MySQL也不例外.用户通过Order by语句即能达到将指定的结果集排序的目的,其实不仅仅是Order by语句,Group by语句,Distinct语句都会隐 ...

  9. 利用windbg查找dictionary导致IIS占CPU100%案例分析(一)

    一.背景 先说下windbg使用场景.各位coder在工作中或多或少都会遇到下面四种情况 1.本地代码好好的,放服务器上运行一段时间后,IIS服务突然占用 w3wp.exe CPU突然100% ,不得 ...

随机推荐

  1. js 压缩 预览 上传图片

    com.js export const compressImage=function (files,fn,preCallbackFn,i) { let newfile = files.files[0] ...

  2. 使用Django+MySQL+Apache+Linux创建简单的博客

    本教程基于慕课网<Django入门与实践>编写,基于CentOS 7 基础知识 什么是django? Django是一个基于Python的高级Web开发框架, 特点:高效,快速,高度集成( ...

  3. 【linux基础】vim多窗口功能

    前言 实现多个文档文件在同一个屏幕上显示多个窗口. 实现过程 在指令列模式输入『:sp {filename}』即可!那个 filename 可有可无, 如果想要在新窗口启动另一个文件,filename ...

  4. android复制包需要修改的几个地方

    1.要看什么情况,若是在同一个eclipse下,那么就需要修改包名.若不在的话,那就可以不用了. 2.这个app_name也是一样. 3.先说下情况,这是我修改好的.原本这个R的是引之前包的,必须要改 ...

  5. HDU1081 最大字段和 压缩数组(单调队列优化)

    最大字段和题型,推荐做题顺序: HDU1003 HDU1024 HDU1081  ZOJ2975 ZOJ2067 #include<cstdio> #include<cstdlib& ...

  6. JS经典面试题

    自己总结了一些JS面试题 希望能够帮助正在找工作的程序猿(●´∀`●) 1.js 实现一个函数对javascript中json 对象进行克隆 var oldObject ="sdf" ...

  7. 【java规则引擎】《Drools7.0.0.Final规则引擎教程》第3章 3.2 KIE API解析

    转载至:https://blog.csdn.net/wo541075754/article/details/75004575 3.2.4 KieServices 该接口提供了很多方法,可以通过这些方法 ...

  8. ThinkPHP 5 insertall 只插入最后一条数据的问题

    问题来源: Steed 2018/1/5 11:30:25 @流年 我用fetchsql查看的sql,发现数据都是最后一条 Steed 2018/1/5 11:30:39 我也不知道是什么问题,我打印 ...

  9. 使用Apriori进行关联分析(二)

    书接上文(使用Apriori进行关联分析(一)),介绍如何挖掘关联规则. 发现关联规则 我们的目标是通过频繁项集挖掘到隐藏的关联规则. 所谓关联规则,指通过某个元素集推导出另一个元素集.比如有一个频繁 ...

  10. Dynamics CRM 2011 通过数据库修改实体字段的长度需要注意的地方

    一.首先打开数据库,我这里以SQL Server 2012数据库为例. 1.选择工具—>选项 ,如图1 图 1 2. 选择表设计器和数据库设计器—>阻止保存要求重新创建表的更改(S)把前面 ...