I have a performance issue in my Spring Boot application when it communicated with Redis that I was hoping someone with experience in this topic could shed some light.
An explanation of what I'm trying to do In short, in my application I have 2 nested maps and 3 list maps that I want to save in Redis and load back into the application when data is needed. The data in the first nested map is quite large, with several levels of non-primitive data types (and their lists). At the moment, I structured the data in Redis using repositories and Redis Hashes with repositories A, B and C and two different ways to search by id for the primary data type ( MyClass ) in A. B and C stores the data referenced by the value from A ( with annotation @Reference ).
Performance Analysis Using JProfiler, I found that the bottleneck was somewhere between my a.findOne() call and the end of reading the response from Redis (before any conversion from byte[] to MyClass happened). I looked at slowlog on my Redis server to check for any slow and blocking actions and did not find them. Each HGETALL command in Redis takes an average of 400 ฮผs (for a complete hash in A, including searching for the hashes specified in B and C). I was struck by the fact that the a.findOne() call time takes from 5 to 20 ms for one instance of MyClass , depending on how large the hashes in B and C. One instance has on average ~ 2500 hash fields when links are turned on to B and C. When this is done ~ 900 times for the first embedded card, I need to wait 10 seconds to get all my data, which is too long. For comparison, another nested nested map that does not have references to C (most of the data) is confined to ~ 10ฮผs in Redis and <1ms in Java.
Does this analysis look like normal behavior when a Redis instance runs locally on the same 2015 MacBook Pro as the Spring boot application? I understand that the complete findOne() method will take longer to complete than the actual HGETALL command in Redis, but I donโt understand why the difference is so big. If anyone could shed light on what is happening under the hood in the Jedis connection code, I would appreciate it.
Examples of my data structure in Java
@RedisHash("myClass") public class MyClass { @Id private String id; private Date date; private Integer someValue; @Reference private Set<C> cs; private someClass someObject; private int somePrimitive; private anotherClass anotherObject; @Reference private B b;
Excerpt from class C (several primitives removed for clarity):
@RedisHash("c") public class C implements Comparable<BasketValue>, Serializable { @Id private String id; private EnumClass someEnum; private aClass anObject; private int aNumber; private int anotherNumber; private Date someDate; private List<CounterClass> counterObjects;
Excerpt from class B:
@RedisHash("b") public class B implements Serializable { @Id private int code; private String productCodes; private List<ListClass> listObject; private yetAnotherClass yetAnotherObject; private Integer someInteger;