基于多级缓存的充电系统优化实践(代码片段)

博科 博科     2022-10-22     325

关键词:

基于多级缓存的充电系统优化实践

原文是发表在文章中,刚看了下文章主要用于转载,因此在随笔中重新发布一下。

摘要

正如前文中《海量并发下充电业务优化实践》所述,在充电过程中由于涉及到大量的实时数据处理,随着设备规模的扩大,各个节点和服务均感受到较大的压力。为了解决这个情况,文中探讨内存缓存组件的使用及相关的过程优化,预计优化后对于Redis的调用频率可以下降50%以上,极大缓解当前Redis的服务压力的同时为未来的系统规模增长打下良好基础。

充电过程中设计的实时数据主要有四类:遥信、遥测、电量和BMS数据。这四类数据在充电过程中持续上传直到充电结束。云端在终端充电过程中的处理压力也是由这些实时数据引起的。

由于当前实时数据处理过程的无状态性和通讯集群与实时数据处理集群之间负载均衡的存在(图1),无法确定由哪个节点来处理哪些终端的实时数据,在此场景下只能依赖中心化的缓存服务,各个处理节点通过中心化的缓存服务来获取数据恢复上下文。

图1 充电和通讯服务部署图
随着终端规模的扩大,虽然实时数据处理集群的性能问题可以通过水平扩展来解决,但是却给中心化的缓存和数据库服务带来了较大压力。此时需要对于充电业务的实时数据处理流程进行优化(图2)。优化从两方面入手:

  1. 引入消息队列来抗击实时数据流量的突然变化,并且将处理节点和终端的对应关系相对固定;
  2. 改变实时数据处理节点的逻辑,由无状态的服务改为带状态和上下文的处理节点。
    其中第1点是其他文章的主题,本文中主要涉及到第2点内容。

图2 优化后充电和通讯服务部署图
因此在目前的程序架构下造成访问Redis和数据库较多的问题。平时对于Redis的每分钟调用次数(TPM)平均值为一百万次(月均值),遇到设备繁忙或者网络波动时,峰值有可能到达两百万次的量级,对于Redis的性能产生了很大的压力,而且也给整个架构带来一些隐患。

图3 Redis单日访问量(TPM_Pool是指各个连接池的每分钟调用数)

对充电业务的优化改造方案计划充分利用现有计算资源,增加内存缓存的使用力度,缓解Redis和数据库的压力。
使用内存缓存需要考虑的有如下三个方面:

  1. 控制内存占用的机制,不至于耗尽计算资源
  2. 内存缓存需要有多样的超时机制,满足复杂的业务需求
  3. 内存缓存跟主缓存之间的同步机制

基于上面一些考虑,在公共技术部门的帮助下确定使用MemoryCache作为内存缓存改造的主要组件。

MemoryCache简介

MemoryCache类是.Net 4.0之后出现的,其命名空间是System.Runtime.Caching(位于 System.Runtime.Caching.dll中)。MemoryCache继承自ObjectCache并实现了IEnumerable和IDisposable接口。

MemoryCache的构造函数有两个:

  • MemoryCache(String, NameValueCollection)
  • MemoryCache(String, NameValueCollection, Boolean)

使用构造函数可以构造出非默认的缓存实例并可以自定义部分属性。

MemoryCache类有7个属性:

名称 描述
CacheMemoryLimit 获取计算机上缓存可使用的内存量(以字节为单位)。
Default 获取对默认 MemoryCache 实例的引用。
DefaultCacheCapabilities 获取缓存提供的功能的说明。
Item[String] 通过使用 MemoryCache 类的实例的默认索引器属性,获取或设置缓存中的值。
Name 获取缓存的名称。
PhysicalMemoryLimit 获取缓存可使用的物理内存的百分比。
PollingInterval 获取在缓存更新其内存统计信息之前需等待的最大时间量。

MemoryCache的属性都是只读属性,设置这些属性可以通过程序配置文件中的 <memoryCache>配置节进行配置。配置实例:

<configuration>
  <system.runtime.caching>
        <memoryCache>
            <namedCaches>
                <add name="Default"
                     cacheMemoryLimitMegabytes="10"
                     physicalMemoryLimitPercentage="10"
                     pollingInterval="00:01:00" />
            </namedCaches>
        </memoryCache>
    </system.runtime.caching>
</configuration>

注意上文中配置节的name属性值为Default,如果写其他名字无法设置MemoryCache.Default的相关属性,只能使用MemoryCache的构造函数构造对应名称的实例来使用。

二 MemoryCache常用方法

1、Add方法

MemoryCache的Add方法有多个重载,该方法的用处是缓存项插入MemoryCache的实例中。

2、AddOrGetExisting方法

MemoryCache的AddOrGetExisting方法有多个重载,该方法的用处是缓存项插入MemoryCache的实例中,如果该缓存的key值已经存在,则返回该key值对应的缓存项。

3、Contains方法

该方法用于检查MemoryCache实例中是否存在某个key值

4、CreateCacheEntryChangeMonitor方法

创建 CacheEntryChangeMonitor 实例。此更改监视器用于监视中指定的缓存条目 keys 集合项更改时触发事件。

5、Get方法

返回某个key值对应的缓存项内容的引用。

6、GetCacheItem方法

从缓存中返回CacheItem实例形式的指定项。

7、GetEnumerator方法

创建缓存项的枚举器,用于循环访问缓存项的集合。

8、GetValues方法

该方法有多个重载,用于批量获取一组key值对应的缓存项。

9、Remove方法

该方法有多个重载,用于从缓存中删除缓存项。

10、Set方法

如果key值存在则更新缓存项,如果不存在则插入缓存项。

11、Trim方法

从缓存中删除总数百分比的缓存项。删除规则参考MemoryCache.Trim 方法 (Int32)

三 MemoryCache如何满足内存缓存的要求

在前文中提到了对于内存缓存的三个基本要求,下面看MemoryCache如何满足这三个方面的要求。
1、控制内存占用

可以通过在配置文件中配置cacheMemoryLimitMegabytesphysicalMemoryLimitPercentage属性分别对于MemoryCache的实例占用内存的绝对值和物理内存相对值进行限制。

2、缓存项失效

在MemoryCache的实例增加缓存项时可以指定缓存项策略,即CacheItemPolicy类对象。该类中有两个属性SlidingExpiration和SlidingExpiration:

  • AbsoluteExpiration:绝对超时时间
  • SlidingExpiration:滑动超时时间,即多少时间未使用即超时

3、跟主缓存之间的同步机制

在指定缓存项策略时还可以在其ChangeMonitors属性中增加监视器,实现监视数据源变化的功能。这些监视器都是派生自ChangeMonitor抽象类,目前在.Net中已经实现的监视器有四种:

  • CacheEntryChangeMonitor
  • FileChangeMonitor
  • HostFileChangeMonitor
  • SqlChangeMonitor

如果有必要的话,可以根据业务时间实现自定义的监视器实现内存缓存和主缓存之间的同步机制。

另外,根据MSDN的资料,MemoryCache的操作是线程安全的,这一点在处理充电实时数据的时候非常重要。

四 充电业务流程优化

内存缓存是Redis数据和部分数据库数据在内存中的映射。每个处理节点的内存缓存只是Redis中数据的子集(图4)。为了使用方便,缓存数据在内存中的数据类型和数据结构跟Redis中的数据组织方式基本一致。

图4 内存缓存和Redis数据集的关系

缓存项在获取时如果获取不到则从Redis中进行恢复,否则直接使用MemoryCache中的数据;MemoryCache缓存项设置后(比如调用Add或者Set方法)如果发现数据有变化则同步设置Redis的值,保持两者的数据同步。对于数据的超时时间则根据不同类型数据上传频率来确定,超时自动清理,有需要时再从Redis中恢复数据。
使用MemoryCache将缓存放在内存中后,不但可以显著减少对于Redis数据的查询。而且只在终端数据变化需要更新时,将数据同步到Redis中也可以减少对于Redis的更新频率。预计改造后对于Redis的查询操作能够减少80%`90%,对于Redis的设置操作可以减少60%~70%。

使用内存缓存对于原业务流程进行优化改造,看起来并不复杂,但是引入内存缓存后带来的不仅仅只是对于缓存存储方式的改变,而是牵扯到一系列相关的流程的变化,包括引入消息队列,合理分配处理接口的负载,多级缓存之间的同步机制等等。这些业务流程的变化对于充电稳定性的影响非常大,在系统运行过程中改变业务流程,犹如在给行驶在高速路上的汽车更换轮胎,如何保证不同流程之间的切换也是需要在设计和部署时需要详细考虑的问题。

五 总结

对于实时数据处理系统而言,有多种多样的架构设计,但是没有一种架构是普适性的。各种架构都有自己的局限性。随着规模的扩大,需要不断地优化架构设计,平衡系统各个模块之间的负载,深入挖掘系统整体性能。正如上文所言,为了解决处理节点的高负载而选择了无状态的处理机制,规模扩大后为了降低中心化的缓存服务(Redis)的压力,又有必要引入内存缓存,缓解Redis的压力,优化处理流程,提高系统内部模块交互的费效比。通过一系列的优化改造,在不增加服务器的情况下,系统整体稳定性和处理性能又会有较大提升,为未来发展打下良好基础。

原文链接:http://www.cnblogs.com/zhu-wj/p/7461104.html

参考资料

优化充电基于matlab粒子群算法电动汽车充电动态优化策略含matlab源码2163期(代码片段)

一、粒子群算法电动汽车充电优化1电动汽车充电负荷估算电动汽车的充电负荷主要与电动汽车起始充电时刻和充电时长相关,而起始充电时刻是由电动汽车用户的到家时间决定的,充电时长主要与电动汽车的行驶里程和充电倍率相... 查看详情

优化求解基于matlab遗传算法求解电动汽车充电管理优化问题含matlab源码1178期(代码片段)

一、简介1遗传算法概述遗传算法(GeneticAlgorithm,GA)是进化计算的一部分,是模拟达尔文的遗传选择和自然淘汰的生物进化过程的计算模型,是一种通过模拟自然进化过程搜索最优解的方法。该算法简单、通... 查看详情

美团外卖搜索基于elasticsearch的优化实践(代码片段)

美团外卖搜索工程团队在Elasticsearch的优化实践中,基于Location-BasedService(LBS)业务场景对Elasticsearch的查询性能进行优化。该优化基于Run-LengthEncoding(RLE)设计了一款高效的倒排索引结构,使检索耗时(... 查看详情

在阿里云服务器下搭建多级缓存(代码片段)

1.学习目标:多级缓存经常用于亿级流量的并发访问数据的优化当中:多级缓存主要分成以下几块的缓存:(1)Nginx本地缓存:用来抵抗的是热数据的高并发的操作,经常会被访问的数据,需要被保留到Nginx的本地缓存当中。对于热... 查看详情

redis进阶学习08--多级缓存(代码片段)

...利用Dockefile部署springboot项目测试CJSON工具类实现Tomcat查询基于ID负载均衡1)原理2)实现Redis缓存预热查询Redis缓存封装Redis工具实现Redis查询Nginx本地缓存本地缓存API实现本地缓存查询OpenResty小结什么是多级缓存传统的缓存... 查看详情

优化调度基于matlab非支配排序遗传算法求解车辆充电调度优化问题含matlab源码2000期(代码片段)

一、遗传算法简介由于国内外人民的生活方式和电动汽车主要购买人群的不同,国内外关于车辆充电调度问题研究的侧重点也不尽相同。我国地大物博,人口众多,交通复杂。主要从以下方面研究:1、通过经济手... 查看详情

基于apachehudi极致查询优化的探索实践(代码片段)

...引信息来加速点查性能。本文分享自华为云社区《华为云基于ApacheHudi极致查询优化的探索实践!》,作者:FI_mengtao。背景湖仓一体(LakeHouse)是一种新的开放式架构,它结合了数据湖和数据仓库的最佳元素ÿ... 查看详情

优化选址基于matlab改进的粒子群算法求解充电桩选址优化问题含matlab源码1964期(代码片段)

一、粒子群算法简介1粒子群算法的概念粒子群优化算法(PSO:Particleswarmoptimization)是一种进化计算技术(evolutionarycomputation)。源于对鸟群捕食的行为研究。粒子群优化算法的基本思想:是通过群体中个体之间的协... 查看详情

redis最佳实践(代码片段)

...架构与概念Redis是一个使用ANSIC编写的开源、支持网络、基于内存、可选持久性的键值对存储数据库。从2015年6月开始,Redis的开发由RedisLabs赞助,而2013年 查看详情

etwvrp基于matlab遗传算法求解带时间窗多电动车充电路径规划问题含matlab源码1966期(代码片段)

一、城市配送系统简介城市配送系统(citydeliverysystem,CDS)的发展是一个城市提高其公共运输能力的关键。目前国内外许多学者对CDS系统进行了深入研究。其中,车辆路径优化问题是城市配送系统中的重要环节,通过对车辆行驶路径的... 查看详情

优化求解基于matlab遗传算法求解峰谷分时电价电动汽车充电负荷优化问题含matlab源码210期(代码片段)

一、电动汽车充电简介近年来,在国内外石油资源紧缺,环境问题日益严重的情况下,电动汽车因具有显著的经济性与环境性,其发展迅速,在中国,至2030年,电动汽车数量将达... 查看详情

eureka源码之server端的多级缓存机制(代码片段)

一、前言上一讲我们讲到了Eureka注册中心的Server端有三级缓存来保存注册信息,可以利用缓存的快速读取来提高系统性能。我们再来细看下:一级缓存:只读缓存readOnlyCacheMap,数据结构ConcurrentHashMap。相当于数据库。二级缓存:... 查看详情

hbase实践(十六)blockcache(代码片段)

...据库一样,优化IO也是HBase提升性能的不二法宝,而提供缓存更是优化的重中之重。根据二八法则,80%的业务请求都集中在20%的热点数据上,因此将这部分数据缓存起就可以极大地提升系统性能。HBase在实现中提供了两种缓存结构... 查看详情

优化选址基于matlab蚁群算法求解电动汽车充电站与换电站选址优化问题含matlab源码1182期(代码片段)

一、简介1概要模拟蚂蚁觅食行为(最短路径原理)设计的算法。讲蚂蚁群觅食的特点抽象出来转化成数学描述。•蚁群算法(AntColonyAlgorithm,ACA)由MarcoDorigo于1992年在他的博士论文中首次提出。•蚂蚁在寻找食物源时,... 查看详情

spark实践——基于sparkstreaming的实时日志分析系统(代码片段)

Spark实践——基于SparkStreaming的实时日志分析系统本文基于《Spark最佳实践》第6章Spark流式计算。我们知道网站用户访问流量是不间断的,基于网站的访问日志,即Weblog分析是典型的流式实时计算应用场景。比如百度统计,它可以... 查看详情

matlab电动汽车路径优化——考虑充电(代码片段)

概述基于电动汽车电量消耗特性,考虑电动车里程、载重、顾客服务时间窗等约束,建立以配送总成本最小为目标的电动车调度优化问题模型;利用自然数编码的遗传算法,求解出电动车的配送路线以及车辆的充... 查看详情

美团外卖搜索基于elasticsearch的优化实践(代码片段)

美团外卖搜索工程团队在Elasticsearch的优化实践中,基于Location-BasedService(LBS)业务场景对Elasticsearch的查询性能进行优化。该优化基于Run-LengthEncoding(RLE)设计了一款高效的倒排索引结构,使检索耗时(... 查看详情

dm中relaylog性能优化实践丨tidb工具分享(代码片段)

...读取最近写入的文件并非通过磁盘,而是读取OS内存中的缓存,因此理论上影响有限。的存在,应用本身再增加一层缓存对latency的影响有限。改为监听channel中的消息。做了一个CPUprofile,从下图可以看出占比较大的主要是syncer/rel... 查看详情