美文网首页
Redis缓存设计之令人兴奋的OutOfMemoryError

Redis缓存设计之令人兴奋的OutOfMemoryError

作者: buildupchao | 来源:发表于2018-06-09 11:19 被阅读0次

先来个自我介绍,博主是Synnex WEBOP OE的Sales部门的一枚Java程序员。

再来介绍下具体情况,Sales部门有3个母系统,它们的年龄和博主相差不多。这半年来,一直在做通过微服务技术重构以及改写旧系统,而博主主要负责的就是大数据量订单查询以及审批,异常状态矫正的所有功能。

其中有这么一种情况,有个子模块需要能够实时查看到所有Open状态以及通过DashBoard进行划分种类的订单。但是鉴于每分钟Open的订单数据量在5W左右,如果每次查询检测都需要直逼DB进行查询,那么就可能会给数据库造成无形的压力(虽然已经采用了读写分离以及分库分表技术,但是每个订单所包含的Detail商品信息就可能上万,所以并不是看到5W个订单,就可以认为数据量很少。更何况,在微服务架构的基础上,我们不能直接进行跨库做表Join操作,而且只能通过网络传输数据)。

1. 刚开始的设计

每分钟Load一次Open态的订单数据,然后全部放入到Redis缓存中。

然而,结果是,因为数据量庞大,序列化和网络传输需要耗费大量的时间,所以产生了如下结果:

2018-05-1421:07:50.691 WARN [qtp683718244-2772]org.eclipse.jetty.server.HttpChannel.handleException:517-/sales-order-portal/

org.springframework.data.redis.serializer.SerializationException:Cannot serialize; nested exception isorg.springframework.core.serializer.support.SerializationFailedException:Failed to serialize object using DefaultSerializer; nested exception isjava.lang.OutOfMemoryError: Java heap space

       at org.springframework.data.redis.serializer.JdkSerializationRedisSerializer.serialize(JdkSerializationRedisSerializer.java:93)

       atorg.springframework.data.redis.core.AbstractOperations.rawHashValue(AbstractOperations.java:171)

       atorg.springframework.data.redis.core.DefaultHashOperations.putAll(DefaultHashOperations.java:129)

       atorg.springframework.data.redis.core.DefaultBoundHashOperations.putAll(DefaultBoundHashOperations.java:86)

       at org.springframework.session.data.redis.RedisOperationsSessionRepository$RedisSession.saveDelta(RedisOperationsSessionRepository.java:778)

       atorg.springframework.session.data.redis.RedisOperationsSessionRepository$RedisSession.access$000(RedisOperationsSessionRepository.java:670)

       atorg.springframework.session.data.redis.RedisOperationsSessionRepository.save(RedisOperationsSessionRepository.java:388)

       atorg.springframework.session.data.redis.RedisOperationsSessionRepository.save(RedisOperationsSessionRepository.java:245)

2. 缓存的重新设计

考虑到查询条件有这么几种情况:

  • 订单header级别的条件

  • 订单line级别的条件

  • 配置信息类的条件

而我们拿到的Open态的订单就属于header级别的数据,所以我们可以直接根据已知的三个条件分别分组,根据分组编号放到三个不同的Cache中,这样不仅避免了每次数据存放的传输以及序列化时间,同时也已经在无形之中减免了一部分查询条件。

2.1 进一步优化查询

后来发现查询条件中还有一个根据订单号以及上述header级别信息进行组合过滤订单的条件,所以又针对此处加了一个特殊逻辑,即,如果有订单号这个查询条件,就先根据订单号进行查询,然后根据header级别信息进行匹配该订单,这样就又有效减免了Redis缓存数据的访问。

好了,项目也已经在UAT环境进行多轮测试以及集成、回归测试,期待上PROD环境的那天!

相关文章

  • Redis缓存设计之令人兴奋的OutOfMemoryError

    先来个自我介绍,博主是Synnex WEBOP OE的Sales部门的一枚Java程序员。再来介绍下具体情况,Sa...

  • 【MyBatis】学习纪要八:缓存(二)

    缓存工具 MyBatis缓存 Ehcache Redis 缓存设计 缓存接口 我们来讨论一下,说到MyBatis,...

  • MI 2021-07-09

    一面 问的设计题偏多 Redis 缓存热点数据 热点数据指的是什么? Redis缓存数据量关注过吗? 如果全部缓存...

  • redis缓存设计

    缓存的利于弊及应用场景 这里我们主要讨论以Redis为代表的基于内存的缓存方案。 缓存的优点 提升访问速度,减少后...

  • redis 分片

    为什么要分片 问题:公司用户量3千万,用户基本信息缓存到redis中,需要内存10G,如何设计Redis的缓存架构...

  • redis 部分详解

    这里我们通过几个场景,不同维度说下Redis的应用。 高性能适合当做缓存 缓存是Redis最常见的应用场景,之所有...

  • Redis 缓存使用(使用代理设计模式)

    Redis 缓存接口 Redis 缓存接口实现 Redis 工具类 Redis 配置 Redis 枚举

  • SpringBoot 使用 Redis 做缓存

    springboot 使用 redis 做缓存 maven 添加 redis 缓存支持