-
背景我们用 JetCache 发现大量 lettuce-ioEventLoop 会执行一些比较重的问题:如反序列化、如 Pub、Sub 分析翻看 JetCache 源码是因为 JetCache 大量用 lettuce 返回的 RedisCommand 做 future 的 callback,虽然 RedisFuture(RedisCommand) 是一个 Future,但是这里似乎只是用来异步通知 bytebuffer 写进来了 我去翻了 lettuce 的源代码, lettuce-ioEventLoop 会执行 IO 读写操作,如果读到一个命令的返回结果,那么会取出 RedisCommand:
问题在于调用 complete 的是 IO 线程,callback 也会由 IO 线程来跑,如果再跑序列化的话,那么性能是很差的(总共没几个线程能执行) 我看了下 Spring Data Redis 的做法,他们没有在 Future 的 callback 里反序列化,而是返回 Byte[] 序列化是调用线程来做的 不知道我的理解对不对,如果是的话,这里似乎能解释为什么我们做大量 get 操作(没有本地缓存的时候)的时候,jetcache 跑得特别慢 |
Beta Was this translation helpful? Give feedback.
Replies: 5 comments 10 replies
-
我没完全看懂你的描述,但你提示了很重要的问题。我理解是这样的: Cache类提供的是异步接口,对于使用jedis的场景来说它本身没有支持异步,所以是同步转异步的“伪异步”,对于lettuce来说就是真正的异步。 CompletableFuture虽然是用来做异步开发的,但它的回调很容易堵塞本来不该堵塞的IO线程,这很容易搞错。JetCache本身虽然没有在这类回调里面执行IO操作,但编解码操作也是比较耗时的(此外lettuce api的回调里面也不该执行解码)。这些操作包括
可以把这些操作丢到另一个线程池里面去执行。 |
Beta Was this translation helpful? Give feedback.
-
调用异步publish就不算了吧,那是不会堵塞的,不过感觉有点不太好,主调方和异步操作可能使用同一个线程池。 |
Beta Was this translation helpful? Give feedback.
-
我看看怎么改一下 |
Beta Was this translation helpful? Give feedback.
-
这个问题比较好改,我已经改好了。但是很多单元测试原来是为同步方式开发的,现在就不能通过,还需要一些时间修复。 |
Beta Was this translation helpful? Give feedback.
-
我已经改好了,你可以试试。 关于你说的过滤的问题,可以通过注解的syncLocal来决定是否打开缓存失效通知。我知道这可能还不够,但不想堆太多只有部分人使用,并且容易被错误使用的功能。以缓存失效通知为例,2.7之前我一直没有做,现在做了也不知道是好事还是坏事,这功能看起来很好,但滥用就会形成广播风暴。 其实我预留了很多扩展点给你这类需求。自己定义一个SpringConfigProvider bean,覆盖notifyMonitorInstaller() 方法,然后覆盖NotifyMonitorInstaller的createMonitor方法(我刚给你弄的),就可以返回自己的CacheNotifyMonitor,你覆盖afterOperation就能实现过滤了。 有时间的话不如帮我看看github action为什么又挂了吧T_T,docker-compose命令找不到了,可能要固定ubuntu的版本才好。 |
Beta Was this translation helpful? Give feedback.
我没完全看懂你的描述,但你提示了很重要的问题。我理解是这样的:
Cache类提供的是异步接口,对于使用jedis的场景来说它本身没有支持异步,所以是同步转异步的“伪异步”,对于lettuce来说就是真正的异步。
CompletableFuture虽然是用来做异步开发的,但它的回调很容易堵塞本来不该堵塞的IO线程,这很容易搞错。JetCache本身虽然没有在这类回调里面执行IO操作,但编解码操作也是比较耗时的(此外lettuce api的回调里面也不该执行解码)。这些操作包括
可以把这些操作丢到另一个线程池里面去执行。