工作阶段性review
一、写在前面
每年都会看看大神们的一年工作总结,感叹一番,从来没有自己的工作总结,现在毕业5~6年,还没有成家立业,有点迷茫,总结一下自己的工作,也算是生涯的一个记录,作为一个非CS专业人士,在学院路技校毕业时啥也不会,就是觉得未来云存储这个方向肯定不错,于是17年毕业后来到中科曙光加入了ParaStor300的团队,负责内核私有客户端的相关工作,非常感谢这份工作让我对分布式系统有了不错的了解,这里有的领导很好,比如为人师长的苗老师,最重要的是有幸在这里认识了一些朋友,不过也有糟心事,在曙光工作1年9个月后,从2019开始来到百度到现在整四年时间从事分布式存储系统BaikalDB的研发工作,在这里真的是学到了很多,虽然和同龄人比技术还是落下了,但是有幸沾团队的光,有一些技术积累,下面就重点review下一下重点工作内容。
二、主要工作
2.1 工作内容
BaikalDB是一个分布式的NewSQL系统,关于BaikalDB这个项目我们团队的leader发布的文章《面向大规模商业系统的数据库设计和实践》作了非常详细的介绍。
[笔记] Designing Access Methods: The RUM Conjecture
The RUM Conjecture
RUM Conjecture非常类似CAP theorem,指对于一个存储系统,出读(Read)、写(Updates)以及空间(Memory)三者之间是一个相互制约的关系,如图
braft snapshot实现
snapshot作用
snapshot是raft算法的四大特性之Log Compaction。
snapshot的主要作用,对本节点来说:
- Log Compaction,在完成Snapshot完成之后,这个时间之前的日志都可以被删除了,这样可以减少日志占用的资源
- 启动加速,启动阶段变为加载Snapshot和追加之后日志两个阶段,而不需要重新执行历史上所有的操作.
对整个raft-group来说,leader和follower会有InstallSnapshot操作,目前,主要有两个地方会触发InstallSnapshot的发送: - Raft中的Follower落后Leader太多,Follower所需要的Raft Log在Leader中已经删除,会触发Leader向Follower发送snapshot
- 当一个Raft Group增加一个peer时,这个peer通过Leader发送snapshot进行数据的初始化
[笔记] The Google File System
Google GFS文件系统是一个面向大规模数据密集型应用的、可伸缩的分布式文件系统。构建在廉价的PC机上,具备良好的容灾能力和性能。
1. Introduction
- 分布式系统中错误是常态,所以需要有持续的监控、错误侦测、灾难冗余以及自动恢复的机制
- 文件普遍较大,达到GB级别,需要重新考虑I/O操作和block大小
- 大部分的文件是追加写而不是覆盖写,一旦写完通常是顺序读取,缓存数据块对性能提升不明显,数据的追加操作是性能优化和原子性保证的主要考量因素。
2. Design Overview
2.1 设计的考量
- 系统由许多廉价的普通组件组成,组件失效是一种常态
- 面向大文件设计,典型文件大小在100MB以上。支持小文件但不做专门优化
- 主要有两种读模式,大块顺序读和小块随机读。应用可以将多个随机读合并排序,然后顺序读取提升性能
- 写模式为大块的顺序追加写入,也支持小块的随机写入,但性能较差
- 支持多客户端高效的并发追加写同一个文件
- 高吞吐优先于低延时
2.2 Interface
- 提供create、delete、open、close、read、write接口
- 支持snapshot和record append
2.3 Architecture
一个GFS集群由一个Master节点和若干个ChunkServer节点组成,Master节点通过多副本保证高可用。
dynamic_cast
C++ dynamic_cast类型转换
dynamic_cast提供类型安全检查,类型之间转换如果不兼容返回null,有时候我们需要在运行时判断一个对象的多态类型,就可以使用dynamic_cast,与Java的instanceof一样,被叫做Capability Query。
多态类型之间的转换包括:
- 子类向父类的向上转换(Up Cast)
- 父类向子类的向下转换(Down Cast)
- 横向转换(Cross Cast)
Database Internals学习
进程地址空间mmap_sem导致的死锁
问题还原
测试同事在进行vdbench测试出现长时间断流,别的同事没有找到原因,问题最终来到我这里,jira记录没有做故障,后端服务进程正常。
现场没有了,还好保存了crash core,需要分析crash来定位。
crash分析
1. 加载我们的内核模块
2. 打印所有进程栈信息,查看可疑的进程栈
|
|
shell read命令的一个坑
shell read命令
使用read命令循环读取文件,按行进行处理时经常用到read命令:
这样做要保证filename文件的内容在读取的时候不会变化,否则可能会与你的处理逻辑不符合,比如
|
|
上述简陋的脚本想umount当前挂载的nfs客户端,但是如果有多个nfs挂载,会漏掉一些,这是因为在umount结束后
/etc/mtab文件也变了,umount的nfs相应的行没了,read按上一次记录的行继续读就出现了问题。
所以这样按行读要确保读的文件至少中间的行不要变化,简单的规避方法是cat filename | while read的方式,但这样
最好filename文件不大,不然很耗内存还可能overflow。
proc文件系统之内存使用
Linux内存使用分析
Linux的proc文件系统提供了很多进程内存使用情况的信息,详细请参考[1][2]
/proc/pid/maps文件
The /proc/PID/maps file containing the currently mapped memory regions and their access permissions.
maps文件的格式为:
- address: the starting and ending address of the region in the process’s address space
- perms: 访问权限,This describes how pages in the region can be accessed.If the process attempts to access memory in a way that is not permitted, a segmentation fault is generated. Permissions can be changed using the mprotect system call.
- r = read
- w = write
- x = execute
- s = shared
- p = private (copy on write)
- offset: 偏移量,如果这段内存是从文件里映射过来的,则偏移量为这段内容在文件中的偏移量,否则为0。
- dev: is the device (major:minor), If the region was mapped from a file, this is the major and minor device number (in hex) where the file lives.
- inode: If the region was mapped from a file, this is the file number.0 indicates that no inode is associated
with the memory region, as the case would be with BSS (uninitialized data). - pathname: The name associated file for this mapping. This field is blank for anonymous mapped regions. There are also special regions with names like:
- [heap]: the heap of the process
- [stack]: the stack of the main process
- [vdso]: the virtual dynamic shared object. It’s used by system calls to switch to kernel mode.
- [vsyscall]: system calls
- 如果是共享库,pathname会重复出现,表示共享库的代码段、数据段等,代码段具有“r-x-”样式,而数据段具有“rw–”样式。
You might notice a lot of anonymous regions. These are usually created by mmap but are not attached to any file. They are used for a lot of miscellaneous things like shared memory or buffers not allocated on the heap. For instance, I think the pthread library uses anonymous mapped regions as stacks for new threads.[4]