并发场景中读写操作安全性除了使用同步锁机制外,另一种更好的实现方式就是使用CopyOnWrite的方式保证读写安全。
写入时复制(CopyOnWrite,简称COW),简单来说,就是平时查询的时候,都不需要加锁,随便访问,只有在更新的时候,才会从原来的数据复制一个副本出来,然后修改这个副本,最后把原数据替换成当前的副本。修改操作的同时,读操作不会被阻塞,而是继续读取旧的数据。这点要跟读写锁区分一下。此做法主要的优点是如果调用者没有修改资源,就不会有副本(private copy)被创建,因此多个调用者只是读取操作时可以共享同一份资源。
这个实现是最近在学习nacos的时候学到的,nacos注册中心的并发性能很好,面对并发场景下的服务注册和服务发现,其实现方式就是使用CopyOnWrite,客户端拉取服务列表时访问的是同一个缓存数据,而当注册服务时,会拿这个缓存数据的副本与注册请求数据做修改处理,最后把副本数据替换为最新的缓存数据,替换操作可以视为原子操作。这种实现方式就避免了使用锁,相对来说性能会好的多。
而同为注册中心的eureka实现方式则是利用了多级缓存,大概思路是分两级缓存,一级只用于读取服务列表,另一级则用于注册时修改注册信息,多级缓存之间定时同步数据,这样也实现了读写安全,但是因为多级缓存需要同步数据,相对来说数据会有较大的延时。