redis日志分析

Posted 夜色架构师

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了redis日志分析相关的知识,希望对你有一定的参考价值。

首先复习一下IO流:

关于读取文件:

  • BufferedReader

从字符输入流中读取文本,缓冲各个字符,从而提供字符、数组和行的高效读取

  • InputStreamReader

字节流通向字符流的桥梁 以UTF-8编码读取

  • FileInputStream

从文件系统中的某个文件中获取输入字节

这三个通常一起使用:

BufferedReader reader=new BufferedReader
        (new InputStreamReader(new FileInputStream(new File(path))));

终的意思是:从path指定的路径中的文件以UFT-8解码,最终生成BufferedReader 对象,读取文件内容

之前在万年历的时候讲解了Calendar类,这里补充一下Java Date类:

在 Java 中获取当前时间,可以使用 java.util.Date 类和 java.util.Calendar 类完成。其中,Date 类主要封装了系统的日期和时间的信息,Calendar 类则会根据系统的日历来解释 Date 对象

Date 类

Date 类表示系统特定的时间戳,可以精确到毫秒。Date 对象表示时间的默认顺序是星期、月、日、小时、分、秒、年。

1. 构造方法

Date 类有如下两个构造方法。

  • Date():此种形式表示分配 Date 对象并初始化此对象,以表示分配它的时间(精确到毫秒),使用该构造方法创建的对象可以获取本地的当前时间。

  • Date(long date):此种形式表示从 GMT 时间(格林尼治时间)1970 年 1 月 1 日 0 时 0 分 0 秒开始经过参数 date 指定的毫秒数。

Date date1 = new Date();    // 调用无参数构造函数
System.out.println(date1.toString());    // 输出:Wed May 18 21:24:40 CST 2016
Date date2 = new Date(60000);    // 调用含有一个long类型参数的构造函数
System.out.println(date2);    // 输出:Thu Jan 0108:01:00 CST 1970

2. 常用方法:

举个例子:假设,某一天特定时间要去做一件事,而且那个时间已经过去一分钟之后才想起来这件事还没有办,这时系统将会提示已经过去了多 长时间。具体的代码如下:

import java.util.Date;
import java.util.Scanner;
public class Test11 
    public static void main(String[] args) 
        Scanner input = new Scanner(System.in);
        System.out.println("请输入要做的事情:");
        String title = input.next();
        Date date1 = new Date(); // 获取当前日期
        System.out.println("[" + title + "] 这件事发生时间为:" + date1);
        try 
            Thread.sleep(60000);// 暂停 1 分钟
         catch (InterruptedException e) 
            e.printStackTrace();
        
        Date date2 = new Date();
        System.out.println("现在时间为:" + date2);
        if (date2.before(date1)) 
            System.out.println("你还有 " + (date2.getTime() - date1.getTime()) / 1000 + " 秒需要去完成【" + title + "】这件事!");
         else 
            System.out.println("【" + title + "】事情已经过去了 " + (date2.getTime() - date1.getTime()) / 1000 + " 秒");
        
    

在该程序中,分别使用 Date 类的无参数构造方法创建了两个 Date 对象。在创建完第一个 Date 对象后,使用 Thread.sleep() 方法让程序休眠 60 秒,然后再创建第二个 Date 对象,这样第二个 Date 对象所表示的时间将会在第一个 Date 对象所表示时间之后,因此“date2.before(date1)”条件表达式不成立,从而执行 else 块中的代码,表示事情已经发生过。

请输入要做的事情:
收快递
【收快递】这件事发生时间为:Fri Oct 12 11:11:07 CST 2018
现在时间为:Fri Oct 12 11:12:07 CST 2018
【收快递】事情已经过去了 60

顺带再次回顾一下Calendar 类:

Calendar 类是一个抽象类,它为特定瞬间与 YEAR、MONTH、DAY_OF—MONTH、HOUR 等日历字段之间的转换提供了一些方法,并为操作日历字段(如获得下星期的日期) 提供了一些方法。

创建 Calendar 对象不能使用 new 关键字,因为 Calendar 类是一个抽象类,但是它提供了一个 getInstance() 方法来获得 Calendar类的对象。getInstance() 方法返回一个 Calendar 对象,其日历字段已由当前日期和时间初始化。

Calendar c = Calendar.getInstance();

Calendar类的常用方法:

Calendar 对象可以调用 set() 方法将日历翻到任何一个时间,当参数 year 取负数时表示公元前。Calendar 对象调用 get() 方法可以获取有关年、月、日等时间信息,参数 field 的有效值由 Calendar 静态常量指定。

Calendar 类中定义了许多常量,分别表示不同的意义。

  • Calendar.YEAR:年份。

  • Calendar.MONTH:月份。

  • Calendar.DATE:日期。

  • Calendar.DAY_OF_MONTH:日期,和上面的字段意义完全相同。

  • Calendar.HOUR:12小时制的小时。

  • Calendar.HOUR_OF_DAY:24 小时制的小时。

  • Calendar.MINUTE:分钟。

  • Calendar.SECOND:秒。

  • Calendar.DAY_OF_WEEK:星期几。

例如,要获取当前月份可用如下代码:

int month = Calendar.getInstance().get(Calendar.MONTH);

注意:如果整型变量 month 的值是 0,表示当前日历是在 1 月份;如果值是 11,则表示当前日历在 12 月份。

使用 Calendar 类处理日期时间的实例如下:

Calendar calendar = Calendar.getInstance(); // 如果不设置时间,则默认为当前时间
calendar.setTime(new Date()); // 将系统当前时间赋值给 Calendar 对象
System.out.println("现在时刻:" + calendar.getTime()); // 获取当前时间
int year = calendar.get(Calendar.YEAR); // 获取当前年份
System.out.println("现在是" + year + "年");
int month = calendar.get(Calendar.MONTH) + 1; // 获取当前月份(月份从 0 开始,所以加 1)
System.out.print(month + "月");
int day = calendar.get(Calendar.DATE); // 获取日
System.out.print(day + "日");
int week = calendar.get(Calendar.DAY_OF_WEEK) - 1; // 获取今天星期几(以星期日为第一天)
System.out.print("星期" + week);
int hour = calendar.get(Calendar.HOUR_OF_DAY); // 获取当前小时数(24 小时制)
System.out.print(hour + "时");
int minute = calendar.get(Calendar.MINUTE); // 获取当前分钟
System.out.print(minute + "分");
int second = calendar.get(Calendar.SECOND); // 获取当前秒数
System.out.print(second + "秒");
int millisecond = calendar.get(Calendar.MILLISECOND); // 获取毫秒数
System.out.print(millisecond + "毫秒");
int dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH); // 获取今天是本月第几天
System.out.println("今天是本月的第 " + dayOfMonth + " 天");
int dayOfWeekInMonth = calendar.get(Calendar.DAY_OF_WEEK_IN_MONTH); // 获取今天是本月第几周
System.out.println("今天是本月第 " + dayOfWeekInMonth + " 周");
int many = calendar.get(Calendar.DAY_OF_YEAR); // 获取今天是今年第几天
System.out.println("今天是今年第 " + many + " 天");
Calendar c = Calendar.getInstance();
c.set(2012, 8, 8); // 设置年月日,时分秒将默认采用当前值
System.out.println("设置日期为 2012-8-8 后的时间:" + c.getTime()); // 输出时间

打印一个日历:

import java.util.Calendar;
public class CalendarDemo 
    public static void main(String[] args) 
        Calendar calendar = Calendar.getInstance();
        calendar.set(2016, 5, 1); // 实际的calendar对象所表示的日期为2016年6月1日
        // 判断2016年6月1日为一周中的第几天
        int index = calendar.get(Calendar.DAY_OF_WEEK) - 1;
        char[] title =  '日', '一', '二', '三', '四', '五', '六' ; // 存放曰历的头部
        int daysArray[][] = new int[6][7];// 存放日历的数据
        int daysInMonth = 31; // 该月的天数
        int day = 1; // 自动增长
        for (int i = index; i < 7; i++) 
            // 填充第一周的日期数据,即日历中的第一行
            daysArray[0][i] = day++;
        
        for (int i = 1; i < 6; i++) 
            // 填充其他周的日历数据,控制行
            for (int j = 0; j < 7; j++) 
                // 如果当前day表示的是本月最后一天,则停止向数组中继续赋值
                if (day > daysInMonth) 
                    i = 6;
                    break;
                
                daysArray[i][j] = day++;
            
        
        System.out.println("------------------2016 年 6 月--------------------\\n");
        for (int i = 0; i < title.length; i++) 
            System.out.print(title[i] + "\\t");
        
        System.out.print("\\n");
        // 输出二元数组daysArray中的元素
        for (int i = 0; i < 6; i++) 
            for (int j = 0; j < 7; j++) 
                if (daysArray[i][j] == 0) 
                    if (i != 0) 
                        // 如果到月末,则完成显示日历的任务,停止该方法的执行
                        return;
                    
                    System.out.print("\\t");
                    continue;
                
                System.out.print(daysArray[i][j] + "\\t");
            
            System.out.print("\\n");
        
    

该程序看似复杂其实很简单。因为 Calendar 类所表示的时间月份是 set() 方法中表示月份的参数值 +1,因此 Calendar 类的实际时间为 2016 年 6 月 1 日。在下面的代码中分别获取 6 月 1 日为本周中的第几天,以便在相应的星期下开始输出 6 月份的日历。程序中的 daysArray 是一个二元数组,该二元数组控制了日历的格式输出,第一个子数组控制日历的行,第二个子数组控制曰历的列,即可输出二元数组中的每一个元素。

------------------20166--------------------

日 一 二 三 四 五 六
   1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31 

关于Hashmap的参数讲解:

习题讲解:

package 任务C__日志分析;

import java.io.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author $范涛之
 * @Description
 * @create 2021-12-03 10:08
 */
public class Test 
    public static void main(String[] args) throws IOException 


        List<String> list = new ArrayList<>();                                           //定义集合
        int savenum = 0;                                                                 //定义存盘次数
        File file = new File("D:\\\\C桌面\\\\CSDN学习计划\\\\技术训练营\\\\redis.log");    //定义文件路径

        /**
         * 分开写的:
         */
//        InputStreamReader inp = new InputStreamReader(new FileInputStream(file),"utf-8");
//        BufferedReader reader = new BufferedReader(inp);

        /**
         * 合起来写:
         */
        BufferedReader reader = new BufferedReader
                (new InputStreamReader(new FileInputStream(new File(String.valueOf(file)))));


        /**
         * 存取文件到list集合中:
         */
        while (reader.read() != -1) 
            list.add(reader.readLine());
        

        /**
         * 统计存盘次数,以数组中出现关键字“DB saved on disk”为基准
         */
        List<String> savedCountList = list.stream()
                .filter(n -> n.contains("DB saved on disk"))
                .collect(Collectors.toList());
        for (String x : savedCountList) 
            savenum++;
        
        // 输出存储数据的次数
        System.out.println("存盘次数为:" + savenum);

        /**
         * 统计出最小存盘时间和最大存盘时间
         */
        //开始存储时间的数组。
        List<String> saveStartTimeList = timeList(list, "Background saving started by pid");
        //调用 toDate 方法,把字符串列表转化为 Date 列表
        List<Date> saveStartTimeDateList = toDate(saveStartTimeList);


        //完成存储时间的数组。
        List<String> saveEndTimeList = timeList(list, "DB saved on disk");

        //调用 toDate 方法,把字符串列表转化为时间列表
        List<Date> saveEndTimeDateList = toDate(saveEndTimeList);


        //存储消耗时间的数组
        List<Long> saveSpentTimeList = new ArrayList<>();
        /**
         * 通过结束时间减去开始时间算出时间差
         */
        for (int i =0;i<saveStartTimeList.size();i++)
            saveSpentTimeList.add(saveEndTimeDateList.get(i).getTime()-saveStartTimeDateList.get(i).getTime());
        
        long maxSaveTime = saveSpentTimeList.get(0);
        long minSaveTime = saveSpentTimeList.get(0);
        /**
         * 在获取的时间查里面筛选处最大和最小的
         */
        for (int i = 0; i < saveSpentTimeList.size(); i++) 
            if (saveSpentTimeList.get(i) < minSaveTime) 
                minSaveTime = saveSpentTimeList.get(i);
             else if (saveSpentTimeList.get(i) > maxSaveTime) 
                maxSaveTime = saveSpentTimeList.get(i);
            
        
        //输出最大、最小存储时间
        System.out.println("最大存储时间为:" + maxSaveTime + "毫秒");
        System.out.println("最小存储时间为:" + minSaveTime + "毫秒")资深架构师教你如何使用elk+redis搭建nginx日志分析平台!

Redis技术专区「优化案例」谈谈使用Redis慢查询日志以及Redis慢查询分析指南

Redis技术专区「优化案例」谈谈使用Redis慢查询日志以及Redis慢查询分析指南

python分析apache和nginx日志文件输出访客ip列表的代码

argparse 代码片段只打印部分日志

elkb+redis建立日志收集分析系统