记一次Perf实践(Xapian读优化)

Xapian 读优化

说一下本文的背景.

我们曾经用Xapian作为内部的倒排索引(只读),在流量比较高的情况下,调用方感知延迟上升,需要对倒排服务进行性能优化.

关于调用方延迟的影响因素

在我们的服务场景里,暂时还没到网卡影响性能的程度,网络协议也没有成为瓶颈,因此调用方观察到的延迟主要还是发生在服务端.

现在的后端服务都是比较成熟的框架,通常会有Accept线程(listen and accept), IO线程(读写request/response,可能还包括编解码),Worker线程(也叫CPU线程,实际干活的).

不同线程间通常是通过队列交换消息,比如Acceptor线程将建立的连接分给IO线程处理IO事件, IO线程将完整解码请求入队等待Worker线程处理, 最终的response也要由队列送回IO线程.

因此,请求的实际服务端延迟通常会受这些因素影响: IO读写编解码, 请求在队列中等待的时间, 实际CPU计算, 所依赖的其他资源, 内部业务的锁竞争.

RocksDB 读优化

RocksDB MultiGet 优化

去年的工作内容中涉及到RocksDB的读写优化,场景分为:大批量写;批量只读;读写TTL

本文回顾批量只读场景下的优化思路,以及记录未来的计划

RocksDB 简单介绍

RocksDB 是一个基于LevelDB优化的持久化KV数据库,其存储结构是LSM-Tree,主要设计用来应对写入密集型工作负载

第一个问题,技术选型

技术选型阶段,我们遇到一个问题,天生为写优化的RocksDB在只读场景是否有必要采用呢?

golang-cpu-profile

用pprof排查CPU Killer

故障背景

最近新上线了一个微服务,主要功能是定期执行各种定时任务,其中一个任务涉及到持有Redis分布式锁,并通过time.Ticker自动续期。(看到这里,也许你已经猜到了问题根源)。

这个服务上线以后,没有出什么大问题,每个任务都按照预期在规定时间内完成。然而,随着时间的推移,任务开始出现超时,甚至有的时候进程已经卡顿到连相关指标监控都无法获取。

Golang的协程同步

问题背景

最近遇到了一个BUG,由于对Golang的同步模型理解不够深入所导致的资源泄露。

伪代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var res Connection
done := make(chan bool)
go func(){
defer close(done)
res, err := acquire(200 * time.Millisecond) //计数器递增
if err != nil {
log.Printf("err: %v", err) //第7行,这里报错
return
}
doWork(res)
}()
select {
case <-done:
case <-time.After(300 * time.Millisecond):
}
release(res) //如果res不等于nil,计数器递减

hdfs-proxy

HDFS-Proxy 技术梳理

问题背景

来自某个需求,希望数据平台可以支持多个不同版本不同认证方式的Hadoop集群。

由于Kerberos的认证是进程级别有效的,因此无法在多线程环境下支持对多Hadoop集群的访问支持。

为了解决多个模块对HDFS的访问需求,因此设计HDFS Proxy模块,透明无侵入地解决这个问题。

设计目标(按重要性排序)

  1. 兼容FileSystem接口,尽量减少接入方的改动成本
  2. 保证性能,减少Proxy环节的性能损耗
  3. 可扩展性,对于集群数量与流量负载都能保持线性可扩展
  4. 完整的Log/Tracing/Metrics信息,减少服务运行状态的不透明
  5. 保持异常信息,在客户端还原服务端捕获到的异常
  6. 不保证线程安全,虽然有一定的锁保护,但不支持多线程同时访问一个FS实例

java-nio-wakeup-trick

探索NIO wakeup内部原理

最近在重新梳理对Kafka的知识,看一遍源码加深印象。源码实现中,Kafka的客户端与服务端都是基于Java NIO机制提高网络IO的效率(当然,这不是唯一因素)。

这里就不再重复说明阻塞/非阻塞,同步/异步IO模型之间的区别了,也不赘述非阻塞IO在不同平台上的实现,例如select,epoll,kqueue等,这些都可以在网络上找到很丰富的文档以及示例。

golang-memory-leak-failure

一次不成功的Golang内存溢出排查

我们的监控服务是以Prometheus加K8S为基础搭建的,运行一段时间后出现了内存溢出的现象,内存RSS占用高达9G,CPU占用60%。以下是整理的排查思路

PProf排查:

我们先查看了应用日志,这些日志内容不断重复,有一定规律,但是当时暂时没有发现特别之处。

memleak-log

接下来,针对Go应用的内存泄露问题,想到了通过官方PProf工具收集应用信息。幸好,Prometheus开启了PProf接口,因此我们可以很方便的得到协程与内存信息。具体过程不表,结果如下:

redis-cluster-specification

Redis集群规范(译)

欢迎来到Redis集群规范。在这里,你可以了解到Redis集群的算法和设计原理。这篇文档还在持续改进过程中,与Redis集群的具体实现保持一致。

主要目标与设计原理

Redis集群设计目标

Redis集群是Redis的分布式实现,主要有如下几个目标,按照重要性依次排列:

  • 高性能以及线性扩展到1000个节点。不使用代理,主从间采用异步复制,并且不支持冲突值的合并操作。
  • 可接受程度的写安全性:当(发生网络分区)客户端可以与系统多数派主节点保持联系时,系统会(尽最大努力)尝试保留来自客户端的所有写数据。通常情况下,可能会有一个小窗口时间内的写数据会丢失。当节点处于少数派网络分区时,这个丢失数据的时间窗口会变得更大。
  • 可用性:当发生网络分区时,如果大多数主节点都可用,并且那些不可用的主节点都至少有一个可用的从节点,那么Redis集群仍然可以保持可用。而且通过从节点迁移命令,可以将具有多个从节点的主节点的从节点分配给没有从节点的主节点。

本文档描述的内容在Redis3.0以及更高版本中实现。

arthas-first-parctice

Arthas 在线诊断初体验

Arthas 是一款阿里出品的Java诊断工具,可以实时监控JVM状态,灵活地线上Debug,具体可以看看它的教程。

虽然功能很强大,但是这次需要排查的问题比较简单,使用watch命令就简单搞定了。

coursera-cloud-computing-specialization

两个月前,机缘巧合之下看到了Coursera上的专项付费系列:云计算 专项。这个系列包含六门课程,主要是讲解了云计算的基础概念,理论,实现和应用。如果你有志于云计算/分布式开发,而且有一定的编程经验(C++与Python),这个系列的课程很适合你。至于我,其实已经从业五年了,重新夯实基础,补齐理论知识是我的主要目的。这个课程的编程题都不难,写的水一些,不用太考虑完美,都能拿到(编程题部分的)满分。

学了一个月多,快把这六门课都学完了,在此记录一下自己的心得体会。