01.Nacos1.4X注册表性能优化方案

105 阅读2分钟

Nacos1.4X注册表性能优化方案

1.问题

  • 注册表就是一个Map,客户端有多个,并发访问注册表,需要加锁否则会出现线程安全问题,性能差
  • 哪怕是用高性能的ConcurrentHashMap在激烈的并发冲突下,性能也不好

.png

2.优化思路

  • 核心就是优化对于Map的读写性能
  • 写性能提升:内存队列+异步任务
  • 读性能提升:写时复制实现读写非阻塞

3.内存队列+异步任务

图示核心思想

9235c0e9d2f043fd14415d6b68da8840.png

具体工作流程

首先 Nacos 客户端发起实例注册,Nacos 服务端把接收的参数包装成一个对象,最后放入到BlookingQueue 里面,注册结束

这个时候,实例注册接口已经结束了,Nacos 客户端已经拿到服务端返回的消息了,然后 Nacos 服务端会在后台新开启一个单线程异步任务,这个任务在不断地取 BlookingQueue 队列中的内容,把这个队列中的内容取出来之后,再把信息写入到注册表中,从而完成注册

优点

  • 接口响应时效更快:其实 Nacos 服务端实例注册接口,它并没有做真正注册的动作,而只是把信息包装好,放入到队列中,接口就结束了。代码逻辑很简单,所以响应时效会更快
  • 保证服务稳定性:哪怕同时有 1 千个、1 万个客户端同时发起实例注册请求接口,最后只是把任务放入到队列中。这个就好比如我们使用消息队列流量削峰一样,后续复杂逻辑的,由消费者慢慢处理,异步任务就相当于消费者
  • 解决写时并发冲突:Nacos 服务端后台,其实是只有一个单线程在处理队列中的任务,把队列中注册实例信息,同步到 Nacos 注册表中,既然是单线程操作,那么在操作写的时候,其实是不用考虑多线程并发写的问题。因为只有一个线程在写,所以不用考虑,但是读操作是由其他线程来操作,会存在读写并发冲突,这个问题是用了写时复制实现读写非阻塞

4.写时复制

图示核心思想

注意:这里用临时复制表只是为了好理解,实际上力度上比这个细,比如临时的Set<Instance>然后覆盖注册表里面某个Cluster对象的Set<Instance>

优点

实现了读写非阻塞,大大提高了性能

缺点

会有短暂的数据不一致情况,在线程还没有把临时注册表覆盖回去,读取的客户端就暂时无法可见