[关闭]
@myecho 2018-06-18T21:57:16.000000Z 字数 3134 阅读 710

中间件比赛

未分类


dubbo多线程通讯分析 https://yq.aliyun.com/articles/272406
https://code.aliyun.com/zy675793960/consumer-agent/
https://code.aliyun.com/zy675793960/provider-agent/
https://code.aliyun.com/zy675793960/benchmarker/
https://cr.console.aliyun.com/

https://blog.csdn.net/ns_code/article/details/14451911
java nio实现后端

调试的办法是进入镜像的 bash (docker run -it —entrypoint=“” /bin/bash) 然后直接运行 start-agent.sh provider-small(medium/large)

docker run -d --name provider-large --network host -v ~/provider-large/logs:/root/logs services:v1:latest provider-large

sudo docker run -d --name consumer --network host -v ~/consumer/logs:/root/logs services:v1 consumer

复赛

初赛考察网络I/O 复赛考察磁盘I/O
消息结构的设计---消息定长还是非定长?在这个场景里边是不是定长好一些?
底层存储结构设计(包括顺序写文件、索引结构设计、文件大小等)
感觉是读取比较随机--索引用hash索引比较合适?kafka的2分查找是不是不太够用?
消息压缩---os buffer能存的更多 kafka是批量压缩
buffer pool设计?
并发写入如何高效?---同一个queue分区?上层通过一层hash到不同分区
磁盘为SSD---随机写的性能不错?只要找到位置---随机读取会性能不错

使用Memory Mapped Files读取索引

kafka没有buffer pool的机制?----依赖pagecache去做buffer

经验谈:
由于KAFKA是基于JVM的,并且任何与Java内存使用打过交道的人都知道两件事:-----java方面的调优也非常重要
▪ 对象的内存开销非常高,通常是实际要存储数据大小的两倍;
▪ 随着数据的增加,java的垃圾收集也会越来越频繁并且缓慢。

基于此,使用文件系统,同时依赖页面缓存就比使用其他数据结构和维护内存缓存更有吸引力:
▪ 不使用进程内缓存,就腾出了内存空间,可以用来存放页面缓存的空间几乎可以翻倍。
▪ 如果KAFKA重启,进行内缓存就会丢失,但是使用操作系统的页面缓存依然可以继续使用。

利用文件系统并且依靠页缓存比维护一个内存缓存或者其他结构要好,它可以直接利用操作系统的页缓存来实现文件到物理内存的直接映射。完成映射之后对物理内存的操作在适当时候会被同步到硬盘上。

在linux中,当dirty page的大小达到了总物理内存大小的10%时,linux操作系统会进行刷盘但不阻塞系统调用的写线程,但若dirty page的大小达到了物理内存大小的20%的时候,写线程就会被阻塞。优化策略是减小最终消息队列序列化到文件的大小,这个可以通过压缩算法达到。
https://github.com/CheYulin/IncrementalSyncShaping/tree/master/comp_summary

去年初赛赛题:
设计一个消息中间件,它支持 Topic 和 Queue,每个 Topic 可以被一个或多个 Queue 订阅。显然,发往 Topic 的消息会被所有的订阅者接收到,而发往某个特定 Queue 的消息只会被它接收到。

消息不能丢失,且对于各个 Queue 消息要保持有序。在此前提下,吞吐量最优者获胜。

要注意的是,生产和消费是分两个阶段进行的:先进行生产,结束后再进行消费。

我的思路很简单,对于每个 Topic 或者 Queue,把所有消息序列化后写入对应的一个文件中。消费时,从磁盘中顺序读取即可。

本题最后瓶颈落在了磁盘 IO 上,所以很多优化也变得无关紧要了。为了充分利用磁盘 IO,一定要确保两点:
* 顺序写入和读取https://ericfu.me/varnish-notes-from-archetect/
* 使用 Linux 内存映射(mmap)技术,也就是 Java nio 包里的 MappedByteBuffer
此外,序列化的过程中尽可能减少内存拷贝,以及避免不必要的 String 序列化、反序列化。

去年经验借鉴:
https://tianchi.aliyun.com/forum/new_articleDetail.html?spm=5176.11165310.0.0.90a57f61Hj90VB&&raceId=231600&postsId=1987

https://tianchi.aliyun.com/forum/new_articleDetail.html?spm=5176.11165310.0.0.90a57f61Hj90VB&&raceId=231600&postsId=2041

https://tianchi.aliyun.com/forum/new_articleDetail.html?spm=5176.11165310.0.0.90a57f61Hj90VB&raceId=231600&postsId=2035

复赛知识总结

总体是要优化磁盘I/O以及内存的使用
几点大方向:
1. 减少I/O次数,可以通过buffer合并请求?
2. 减少I/O过程的拷贝次数,通过linux mmap技术?
3. 优化cache使用 包括cpu cache以及pagecache
4. 减少文件个数,避免inode个数暴涨,优化innode缓存的使用
5. 需要使用buffer pool么?还是直接依赖os的buffer?---不太可行,内存不够

实现细节
1. 底层每条消息的存储结构设计,如何省空间?
2. 存储层,文件读写方式如何?顺序写?随机读?Java的文件I/O好好看下
3. index索引结构的设计,如果快速找到某个message在磁盘中的位置

预备知识:
1. 操作系统文件I/O的流程,理解pageCache以及拷贝过程
2. java 文件I/O API使用
3. 数据库的索引结构的设计?可参考某些kv存储系统(带外存)的索引设计
4. 压缩---在这个场景中看起来不太可行

参考资料:
kafka底层存储实现:
https://www.zybuluo.com/myecho/note/575930
https://www.quora.com/What-are-the-differences-between-Apache-Kafka-and-RabbitMQ
https://www.jianshu.com/p/453c6e7ff81c
https://blog.csdn.net/quhongwei_zhanqiu/article/details/39144223
https://blog.csdn.net/column/details/learningrocketmq.html
https://blog.csdn.net/quhongwei_zhanqiu/article/details/39143755
https://blog.csdn.net/quhongwei_zhanqiu/article/details/39153195
https://yq.aliyun.com/articles/66110

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注