阅读指南

程序厨大约 9 分钟C++项目实战程序员基地高性能日志面试互联网校招程序厨

高性能日志

一:项目背景

在软件开发和线上环境下,日志是我们排查问题的最主要手段,它就像程序的眼睛和耳朵,通过日志,我们开发人员可以监控程序的运行状态,方便监控业务的运行状态,方便我们发现潜在问题,甚至追溯历史问题。

日志系统的重要性:

故障排查:当应用程序出现异常或崩溃时,日志是快速定位问题根源的关键信息来源。通过查看日志,可以了解出错前后的系统状态和操作,快速找到问题所在。

性能监控:日志可以记录应用程序的关键性能指标,如响应时间、吞吐量、资源使用率等。通过定期分析这些日志,可以及时发现性能瓶颈并进行优化。

业务分析:除了故障排查和性能监控,日志还可以用于业务分析。例如,通过分析用户操作日志,可以了解用户行为模式,为产品优化和营销策略提供数据支持。

传统的日志有很多不足:

性能瓶颈:传统日志系统通常采用简单的文件写入方式,处理大量日志数据时,会导致延迟增加,影响磁盘I/O速度,影响正常的业务运行。

资源占用:会占用大量CPU、内存和磁盘空间,导致系统资源紧张,影响正常的业务运行。

安全性不足:都是明文存储,而日志里经常会存储敏感信息,很容易泄漏。

可扩展性差:传统日志系统往往采用固定的日志格式和存储方式,难以适应新的需求变化,系统维护和升级困难。

所以一般线上,特别是客户端,比较少会打开日志功能,或者不会频繁的写日志,只会写入一些Error级别的日志。

二:项目目标

为了解决这些问题,很多公司会开发高性能日志系统,目标就是可以在线上频繁的写日志,而又不会影响正常业务的运行。

比较典型的就是:

腾讯的xlog:https://cloud.tencent.com/developer/article/1005575open in new window

美团的Logan:https://tech.meituan.com/2018/10/11/logan-open-source.htmlopen in new window

我们目标做一个具有低延迟、资源占用少、安全可靠并且易于扩展能力的日志库,满足线上软件的需求。

三:高性能日志系统的需求

鉴于日志系统的重要性,一个高性能的日志系统对于确保应用程序的稳定运行和高效运维就至关重要。

下面是我们高性能日志系统的主要需求:

低延迟:日志记录操作应该尽可能快,避免对应用程序的正常运行产生负面影响。特别是在高并发场景下,日志系统的延迟必须控制在毫秒级甚至更低。

高吞吐量:随着程序规模的扩大,日志数据量也会急剧增加。日志系统需要具备处理大量日志数据的能力,确保不会因为日志堆积而导致系统性能下降。

资源占用小:日志系统本身不应该成为系统的资源瓶颈。它应该能够高效地利用系统资源,如CPU、内存和磁盘空间,特别是磁盘空间,写个日志如果占用用户的几G磁盘空间,那可能会被客诉。

可靠性:日志系统必须具有高可用性,我们需要确保在应用程序崩溃或系统异常时,日志数据不会丢失。

可扩展性:日志系统的需求也会不断变化。因此,日志系统需要具备可扩展性,能够方便地添加新功能、支持新的日志格式等。

安全性:日志数据往往包含敏感信息,如用户密码、系统配置等。因此,日志系统需要具备加密能力,避免明文存储。

四、项目介绍

针对以上需求,我们训练营研发了高性能日志的项目,旨在做一个具有低延迟、资源占用少、安全可靠并且易于扩展能力的日志库,满足线上软件的需求。

目标是通过本项目,帮助大家掌握这些技术的灵活运用。

日志系统的架构设计

从0到1开发任何稍微大点的程序都需要进行架构设计。

在架构设计中,我们需要特别注意以下几点:

可扩展性:这是最重要的一点,随着系统规模的扩大,日志量也会迅速增长,因此架构需要能够水平扩展,应对后续的需求。

安全性:日志中可能包含敏感信息,如用户密码、业务数据等。因此,在架构设计中需要充分考虑数据加密等安全措施。

易用性:架构设计应尽可能简单清晰,对外的API也要简单易用,方便应用程序简易的调用接口配置相关参数和写日志,减少出错的概率。

你将会收获:

如何做架构分析

如何设计日志系统的架构

项目编码规范的制定

C++ 压缩与解压缩,如何优化压缩率

为了优化日志系统的磁盘空间占用,肯定需要利用压缩技术。

本项目,我们会通过C++引入一些三方库,有Zlib和Zstd,利用这些三方库完成压缩的能力,在保证压缩速度的同事,最大限度的优化压缩率。

优化压缩率的策略包括:

选择合适的压缩算法和压缩库。

调整压缩参数:大多数压缩算法都提供了参数调整功能,如压缩级别、缓冲区大小等。通过调整这些参数,可以在压缩速度和压缩率之间找到最佳平衡点。

你将会收获:

如何通过C++集成压缩库

如何使用Zlib

如何使用Zstd

如何优化压缩率

C++ 加解密,对称加密与非对称加密

日志系统中可能包含敏感信息,肯定需要加密技术。

本项目,我们也会引入一些三方库完成加解密的能力,常用的三方库有OpenSSL、Crypto++、Mbedtls等。

我们既会使用对称加密技术,也会使用非对称加密技术。

对称加密:使用相同的密钥进行加密和解密。对称加密算法速度快,适合处理大量数据。

非对称加密:使用一对公钥和私钥进行加密和解密。公钥用于加密数据,私钥用于解密数据。非对称加密算法安全性高,但速度较慢。

你将会收获:

如何在C++中集成加密库

如何使用对称加密

如何使用非对称加密

对称加密和非对称加密的搭配使用

C++ 序列化与反序列化

序列化是将对象状态转换为可存储或可传输的格式的过程,而反序列化则是将存储或传输的格式还原为对象状态的过程。

本项目中,会使用序列化技术将日志对象转换为二进制数据,方便进行存储或传输。

C++提供了多种序列化方法,如Boost.Serialization库、Protocol Buffers等。我们会通过C++集成使用Protobuf,来确保日志数据的高效存储和传输。

你将会收获:

如何在C++中集成Protobuf

如何设计proto结构

如何使用序列化和反序列化

线程池的设计与调度使用

日志系统通常需要处理大量的并发日志请求,为了提高性能,肯定需要并发编程,肯定需要多线程,而多线程开发中,可以使用线程池来管理并发任务。

你将会收获:

如何设计线程池,包括线程数量的确定、任务队列的实现、线程调度策略等

如何实现线程池

如何实现strand模块,通过strand执行并发任务,减少多线程开发带来的数据竞争风险

mmap高效文件读写操作

在日志系统中,文件读写操作是不可避免的。为了提高文件读写效率,可以使用mmap(内存映射文件)技术。mmap将文件内容映射到进程的地址空间中,使得文件读写操作可以通过内存访问来实现,从而大大提高了文件读写速度。

你将会收获:

如何使用mmap优化文件读写策略

如何在Linux中使用mmap

如何在Windows中使用mmap

如何封装mmap模块,让文件读写像操作普通的动态数组一样简单

跨平台组件的设计

日志系统通常需要在不同操作系统上运行。因此,在设计时需要充分考虑跨平台兼容性。

这包括使用平台相关的API、避免选用非跨平台的三方库等。

你将会收获:

如何设计开发跨平台组件

抽象平台差异:通过抽象层来封装不同操作系统的差异,对外暴露平台无关的接口,使得上层代码可以跨平台运行

C++的很多新特性

C++11后引入了许多新特性,如智能指针、lambda表达式、线程库等。用过C++98的朋友应该知道,这些新特性真的极大的提高了我们的开发效率。

你将会收获:

C++相关技术,继承、封装、多态、模板、RAII之类的各种技术,这里咱就不多介绍了,实战中见

常用的C++组件,vector、string、list等等,我们会在理解这些组件原理的前提下,灵活使用它们

C++的新特性的使用,tuple、atomic、mutex、string_view、initializer_list等等

智能指针的使用,包括shared_ptr、unique_ptr、自定义deleter等

lambda表达式:化函数对象的定义和使用

线程库:我们会使用C++11的thread、future等设计线程池

filesystem:使用C++17的filesystem库,使文件操作非常方便

chrono:时间相关操作,chrono基本就够用,我们会参考chrono底层的ratio,设计出space,方便空间单位的转换,比如bytes、kilobytes、megabytes、gigabytes、terabytes

fmt:类似于C++20的std::format

项目大纲:

项目代码:

需要完整代码和文档的同学可以,添加微信咨询,记得备注哈