Redis используется все шире, и когда мы сталкиваемся с узкими местами в производительности, как их решать?
Смотрите статью, соответствующую проектуspring-boot-skill
Схема сериализации Redis
Spring Boot Redis
Spring Boot Data Redis
Он предоставляет нам возможность plug-and-play, большинство конфигураций по умолчанию отвечают нашим потребностям, а схема сериализации является родной.JdkSerializationRedisSerializer
RedisTemplate.java
if (defaultSerializer == null) {
defaultSerializer = new JdkSerializationRedisSerializer(
classLoader != null ? classLoader : this.getClass().getClassLoader());
}
Конечно, мы также можем выбратьSpring Boot Data Redis
другие схемы сериализации могут быть настроены.
RedisSerializer
реализация
На этой основе мы можем настроить собственную схему сериализации.
Пользовательская схема сериализации JSON
FastJsonRedisSerializer.java
public class FastJsonRedisSerializer<T> implements RedisSerializer<T> {
private FastJsonConfig fastJsonConfig = new FastJsonConfig();
private Class<T> type;
public FastJsonRedisSerializer(Class<T> type) {
this.type = type;
}
public FastJsonConfig getFastJsonConfig() {
return fastJsonConfig;
}
public void setFastJsonConfig(FastJsonConfig fastJsonConfig) {
this.fastJsonConfig = fastJsonConfig;
}
@Override
public byte[] serialize(T t) throws SerializationException {
if (t == null) {
return new byte[0];
}
try {
return JSON.toJSONBytes(
fastJsonConfig.getCharset(),
t,
fastJsonConfig.getSerializeConfig(),
fastJsonConfig.getSerializeFilters(),
fastJsonConfig.getDateFormat(),
JSON.DEFAULT_GENERATE_FEATURE,
fastJsonConfig.getSerializerFeatures()
);
} catch (Exception ex) {
throw new SerializationException("Could not serialize: " + ex.getMessage(), ex);
}
}
@Override
public T deserialize(byte[] bytes) throws SerializationException {
if (bytes == null || bytes.length == 0) {
return null;
}
try {
return (T) JSON.parseObject(
bytes,
fastJsonConfig.getCharset(),
type,
fastJsonConfig.getParserConfig(),
fastJsonConfig.getParseProcess(),
JSON.DEFAULT_PARSER_FEATURE,
fastJsonConfig.getFeatures()
);
} catch (Exception ex) {
throw new SerializationException("Could not deserialize: " + ex.getMessage(), ex);
}
}
}
Конечно, это основано наfastjson
Решение для сериализации не только обеспечивает меньший объем, чем сериализация JDK, но и более быструю сериализацию и десериализацию.
Схема сериализации FST и Kryo
Вставьте соответствующий код здесь, подробности можно увидетьredis-serializer-line
Сравнение производительности (тест)
JDK
,FastJson
,FST
,Kryo
Результаты теста следующие, элементы теста видныredis-serializer-line
原生JDK序列化方案[序列化100000次]耗时:2160 ms, 大小 44000000
原生JDK序列化方案[序列化100000次]耗时:1406 ms, 大小 44000000
FastJson序列化方案[序列化100000次]耗时:679 ms, 大小 18800000
FastJson序列化方案[序列化100000次]耗时:289 ms, 大小 18800000
FST序列化方案[序列化100000次]耗时:273 ms, 大小 10400000
FST序列化方案[序列化100000次]耗时:130 ms, 大小 10400000
Kryo序列化方案[序列化100000次]耗时:498 ms, 大小 14000000
Kryo序列化方案[序列化100000次]耗时:215 ms, 大小 14000000
Суммировать
FST
иKryo
Обеспечивает меньший размер и более высокую скорость сериализации, чемFastjson
Больше преимуществ производительности. Однако объекты, которые необходимо сериализовать, должны быть обработаны заранее.register
, что увеличивает сложность кодирования. иKryo
Поток небезопасен и требует дополнительной обработки, например,KryoPool
Выполнить объединение.
Заменив схему сериализации, можно решитьRedis IO
Проблема избыточного давления, повышения производительности.
иностранный язык
Dubbo
Проект предоставляет большое количество решений для сериализации, которые имеют небольшой размер и быструю передачу ввода-вывода, поэтому они более эффективны в сфере микросервисов.Spring Cloud
больше преимуществ производительности. Мы можем ссылаться на следующее при реализации сериализацииDubbo
Исходный код для кодирования, в конце концов, код, который был улучшен и протестирован, очень ценен для справки.
Например,Dubbo
существуетFST
Когда объект создан, объект, который необходимо сериализовать, будет обработан.registerClass
, что значительно повышает производительность. И при использовании Kryo не толькоregister
Сериализованные объекты также необходимо выполнять для базовых типов.register
.
FST
Базовый тип был зарегистрирован сам по себе, поэтомуFST
по сравнению с простотой использованияKryo
больше преимуществ, также обеспечивает@Version
Управление версиями новых полей POJO.
Добро пожаловать, чтобы обратить на меня внимание, я буду время от времени обновлять небольшие навыки и небольшие средства в развитии. Гит-адрес:git ee.com/soft men G/tickets…
Пример сериализации в Dubbo
FstFactory.java
public FstFactory() {
SerializableClassRegistry.getRegisteredClasses().keySet().forEach(conf::registerClass);
}
Kryo.java
public Kryo create() {
if (!kryoCreated) {
kryoCreated = true;
}
Kryo kryo = new CompatibleKryo();
// TODO
// kryo.setReferences(false);
kryo.setRegistrationRequired(registrationRequired);
kryo.addDefaultSerializer(Throwable.class, new JavaSerializer());
kryo.register(Arrays.asList("").getClass(), new ArraysAsListSerializer());
kryo.register(GregorianCalendar.class, new GregorianCalendarSerializer());
kryo.register(InvocationHandler.class, new JdkProxySerializer());
kryo.register(BigDecimal.class, new DefaultSerializers.BigDecimalSerializer());
kryo.register(BigInteger.class, new DefaultSerializers.BigIntegerSerializer());
kryo.register(Pattern.class, new RegexSerializer());
kryo.register(BitSet.class, new BitSetSerializer());
kryo.register(URI.class, new URISerializer());
kryo.register(UUID.class, new UUIDSerializer());
UnmodifiableCollectionsSerializer.registerSerializers(kryo);
SynchronizedCollectionsSerializer.registerSerializers(kryo);
// now just added some very common classes
// TODO optimization
kryo.register(HashMap.class);
kryo.register(ArrayList.class);
kryo.register(LinkedList.class);
kryo.register(HashSet.class);
kryo.register(TreeSet.class);
kryo.register(Hashtable.class);
kryo.register(Date.class);
kryo.register(Calendar.class);
kryo.register(ConcurrentHashMap.class);
kryo.register(SimpleDateFormat.class);
kryo.register(GregorianCalendar.class);
kryo.register(Vector.class);
kryo.register(BitSet.class);
kryo.register(StringBuffer.class);
kryo.register(StringBuilder.class);
kryo.register(Object.class);
kryo.register(Object[].class);
kryo.register(String[].class);
kryo.register(byte[].class);
kryo.register(char[].class);
kryo.register(int[].class);
kryo.register(float[].class);
kryo.register(double[].class);
for (Class clazz : registrations) {
kryo.register(clazz);
}
SerializableClassRegistry.getRegisteredClasses().forEach((clazz, ser) -> {
if (ser == null) {
kryo.register(clazz);
} else {
kryo.register(clazz, (Serializer) ser);
}
});
return kryo;
}