优化缓存电表信息获取,采用分页方式
This commit is contained in:
parent
1284898376
commit
142f864544
@ -9,6 +9,7 @@ using JiShe.CollectBus.Serializer;
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Volo.Abp.Application.Services;
|
using Volo.Abp.Application.Services;
|
||||||
|
|
||||||
@ -43,7 +44,7 @@ public abstract class CollectBusAppService : ApplicationService
|
|||||||
throw new Exception($"{nameof(GetMeterRedisCacheDictionaryData)} 获取缓存的表计信息失败,参数异常,-101");
|
throw new Exception($"{nameof(GetMeterRedisCacheDictionaryData)} 获取缓存的表计信息失败,参数异常,-101");
|
||||||
}
|
}
|
||||||
|
|
||||||
//通过lua脚本一次性获取所有缓存内容
|
var meterInfos = new Dictionary<string, Dictionary<string, T>>();
|
||||||
var luaScript = @"
|
var luaScript = @"
|
||||||
local results = {}
|
local results = {}
|
||||||
for i, key in ipairs(KEYS) do
|
for i, key in ipairs(KEYS) do
|
||||||
@ -51,28 +52,41 @@ public abstract class CollectBusAppService : ApplicationService
|
|||||||
results[i] = {key, data}
|
results[i] = {key, data}
|
||||||
end
|
end
|
||||||
return results";
|
return results";
|
||||||
var merterResult = await FreeRedisProvider.Instance.EvalAsync(luaScript, redisKeys); //传递 KEYS
|
|
||||||
|
// 分页参数:每页处理10000个键
|
||||||
|
int pageSize = 10000;
|
||||||
|
int totalPages = (int)Math.Ceiling(redisKeys.Length / (double)pageSize);
|
||||||
|
|
||||||
|
for (int page = 0; page < totalPages; page++)
|
||||||
|
{
|
||||||
|
// 分页获取当前批次的键
|
||||||
|
var batchKeys = redisKeys
|
||||||
|
.Skip(page * pageSize)
|
||||||
|
.Take(pageSize)
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
// 执行Lua脚本获取当前批次数据
|
||||||
|
var merterResult = await FreeRedisProvider.Instance.EvalAsync(luaScript, batchKeys);
|
||||||
if (merterResult == null)
|
if (merterResult == null)
|
||||||
{
|
{
|
||||||
throw new Exception($"{nameof(GetMeterRedisCacheDictionaryData)} 获取缓存的表计信息失败,没有获取到数据,-102");
|
throw new Exception($"{nameof(GetMeterRedisCacheDictionaryData)} 获取缓存的表计信息失败,第 {page + 1} 页数据未返回,-102");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 解析结果(结果为嵌套数组)
|
// 解析当前批次的结果
|
||||||
var meterInfos = new Dictionary<string, Dictionary<string, T>>(); ;
|
|
||||||
if (merterResult is object[] arr)
|
if (merterResult is object[] arr)
|
||||||
{
|
{
|
||||||
foreach (object[] item in arr)
|
foreach (object[] item in arr)
|
||||||
{
|
{
|
||||||
string key = (string)item[0];//集中器地址对应的Redis缓存Key
|
string key = (string)item[0];
|
||||||
object[] fieldsAndValues = (object[])item[1];//缓存Key对应的Hash表数据集合
|
object[] fieldsAndValues = (object[])item[1];
|
||||||
var redisCacheKey = $"{string.Format(RedisConst.CacheMeterInfoKey, systemType, serverTagName, meterType, timeDensity)}";
|
var redisCacheKey = $"{string.Format(RedisConst.CacheMeterInfoKey, systemType, serverTagName, meterType, timeDensity)}";
|
||||||
string focusAddress = key.Replace(redisCacheKey, "");//集中器地址
|
string focusAddress = key.Replace(redisCacheKey, "");
|
||||||
|
|
||||||
var meterHashs = new Dictionary<string, T>();
|
var meterHashs = new Dictionary<string, T>();
|
||||||
for (int i = 0; i < fieldsAndValues.Length; i += 2)
|
for (int i = 0; i < fieldsAndValues.Length; i += 2)
|
||||||
{
|
{
|
||||||
string meterld = (string)fieldsAndValues[i];//表ID
|
string meterId = (string)fieldsAndValues[i];
|
||||||
string meterStr = (string)fieldsAndValues[i + 1];//表详情数据
|
string meterStr = (string)fieldsAndValues[i + 1];
|
||||||
|
|
||||||
T meterInfo = default!;
|
T meterInfo = default!;
|
||||||
if (!string.IsNullOrWhiteSpace(meterStr))
|
if (!string.IsNullOrWhiteSpace(meterStr))
|
||||||
@ -81,16 +95,33 @@ public abstract class CollectBusAppService : ApplicationService
|
|||||||
}
|
}
|
||||||
if (meterInfo != null)
|
if (meterInfo != null)
|
||||||
{
|
{
|
||||||
meterHashs[meterld] = meterInfo;
|
meterHashs[meterId] = meterInfo;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw new Exception($"{nameof(GetMeterRedisCacheDictionaryData)} 获取缓存的表计信息集中器缓存{key}数据的{meterld}处理异常,-102");
|
throw new Exception($"{nameof(GetMeterRedisCacheDictionaryData)} 缓存表计数据异常,集中器 {key} 的表计 {meterId} 解析失败,-103");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 合并到总结果,若存在重复key则覆盖
|
||||||
|
if (meterInfos.ContainsKey(focusAddress))
|
||||||
|
{
|
||||||
|
foreach (var kvp in meterHashs)
|
||||||
|
{
|
||||||
|
meterInfos[focusAddress][kvp.Key] = kvp.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
meterInfos[focusAddress] = meterHashs;
|
meterInfos[focusAddress] = meterHashs;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new Exception($"{nameof(GetMeterRedisCacheDictionaryData)} 第 {page + 1} 页数据解析失败,返回类型不符,-104");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return meterInfos;
|
return meterInfos;
|
||||||
}
|
}
|
||||||
@ -107,12 +138,15 @@ public abstract class CollectBusAppService : ApplicationService
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
protected async Task<List<T>> GetMeterRedisCacheListData<T>(string[] redisKeys, string systemType, string serverTagName, string timeDensity, MeterTypeEnum meterType) where T : class
|
protected async Task<List<T>> GetMeterRedisCacheListData<T>(string[] redisKeys, string systemType, string serverTagName, string timeDensity, MeterTypeEnum meterType) where T : class
|
||||||
{
|
{
|
||||||
if (redisKeys == null || redisKeys.Length <= 0 || string.IsNullOrWhiteSpace(systemType) || string.IsNullOrWhiteSpace(serverTagName) || string.IsNullOrWhiteSpace(timeDensity))
|
if (redisKeys == null || redisKeys.Length <= 0 ||
|
||||||
|
string.IsNullOrWhiteSpace(systemType) ||
|
||||||
|
string.IsNullOrWhiteSpace(serverTagName) ||
|
||||||
|
string.IsNullOrWhiteSpace(timeDensity))
|
||||||
{
|
{
|
||||||
throw new Exception($"{nameof(GetMeterRedisCacheListData)} 获取缓存的表计信息失败,参数异常,-101");
|
throw new Exception($"{nameof(GetMeterRedisCacheListData)} 参数异常,-101");
|
||||||
}
|
}
|
||||||
|
|
||||||
//通过lua脚本一次性获取所有缓存内容
|
var meterInfos = new List<T>();
|
||||||
var luaScript = @"
|
var luaScript = @"
|
||||||
local results = {}
|
local results = {}
|
||||||
for i, key in ipairs(KEYS) do
|
for i, key in ipairs(KEYS) do
|
||||||
@ -120,27 +154,46 @@ public abstract class CollectBusAppService : ApplicationService
|
|||||||
results[i] = {key, data}
|
results[i] = {key, data}
|
||||||
end
|
end
|
||||||
return results";
|
return results";
|
||||||
var merterResult = await FreeRedisProvider.Instance.EvalAsync(luaScript, redisKeys); //传递 KEYS
|
|
||||||
|
// 分页参数:每页10000个键
|
||||||
|
int pageSize = 10000;
|
||||||
|
int totalPages = (int)Math.Ceiling(redisKeys.Length / (double)pageSize);
|
||||||
|
|
||||||
|
for (int page = 0; page < totalPages; page++)
|
||||||
|
{
|
||||||
|
// 分页获取当前批次键
|
||||||
|
var batchKeys = redisKeys
|
||||||
|
.Skip(page * pageSize)
|
||||||
|
.Take(pageSize)
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
// 执行Lua脚本获取当前页数据
|
||||||
|
var merterResult = await FreeRedisProvider.Instance.EvalAsync(luaScript, batchKeys);
|
||||||
if (merterResult == null)
|
if (merterResult == null)
|
||||||
{
|
{
|
||||||
throw new Exception($"{nameof(GetMeterRedisCacheListData)} 获取缓存的表计信息失败,没有获取到数据,-102");
|
throw new Exception($"{nameof(GetMeterRedisCacheListData)} 第 {page + 1} 页数据未返回,-102");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 解析结果(结果为嵌套数组)
|
// 解析当前页结果
|
||||||
var meterInfos = new List<T>(); ;
|
|
||||||
if (merterResult is object[] arr)
|
if (merterResult is object[] arr)
|
||||||
{
|
{
|
||||||
foreach (object[] item in arr)
|
foreach (object[] item in arr)
|
||||||
{
|
{
|
||||||
string key = (string)item[0];//集中器地址对应的Redis缓存Key
|
string key = (string)item[0];
|
||||||
object[] fieldsAndValues = (object[])item[1];//缓存Key对应的Hash表数据集合
|
object[] fieldsAndValues = (object[])item[1];
|
||||||
var redisCacheKey = $"{string.Format(RedisConst.CacheMeterInfoKey, systemType, serverTagName, meterType, timeDensity)}";
|
var redisCacheKey = string.Format(
|
||||||
string focusAddress = key.Replace(redisCacheKey, "");//集中器地址
|
RedisConst.CacheMeterInfoKey,
|
||||||
|
systemType,
|
||||||
|
serverTagName,
|
||||||
|
meterType,
|
||||||
|
timeDensity
|
||||||
|
);
|
||||||
|
string focusAddress = key.Replace(redisCacheKey, "");
|
||||||
|
|
||||||
for (int i = 0; i < fieldsAndValues.Length; i += 2)
|
for (int i = 0; i < fieldsAndValues.Length; i += 2)
|
||||||
{
|
{
|
||||||
string meterld = (string)fieldsAndValues[i];//表ID
|
string meterId = (string)fieldsAndValues[i];
|
||||||
string meterStr = (string)fieldsAndValues[i + 1];//表详情数据
|
string meterStr = (string)fieldsAndValues[i + 1];
|
||||||
|
|
||||||
T meterInfo = default!;
|
T meterInfo = default!;
|
||||||
if (!string.IsNullOrWhiteSpace(meterStr))
|
if (!string.IsNullOrWhiteSpace(meterStr))
|
||||||
@ -153,11 +206,18 @@ public abstract class CollectBusAppService : ApplicationService
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw new Exception($"{nameof(GetMeterRedisCacheListData)} 获取缓存的表计信息集中器缓存{key}数据的{meterld}处理异常,-103");
|
throw new Exception(
|
||||||
|
$"{nameof(GetMeterRedisCacheListData)} 表计 {meterId} 解析失败(页 {page + 1}),-103"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new Exception($"{nameof(GetMeterRedisCacheListData)} 第 {page + 1} 页数据格式错误,-104");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return meterInfos;
|
return meterInfos;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,13 +13,13 @@ using Microsoft.AspNetCore.Mvc;
|
|||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using JiShe.CollectBus.IoTDBProvider.Context;
|
using JiShe.CollectBus.IoTDBProvider.Context;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using JiShe.CollectBus.Common.Helpers;
|
|
||||||
using JiShe.CollectBus.IotSystems.AFNEntity;
|
using JiShe.CollectBus.IotSystems.AFNEntity;
|
||||||
using JiShe.CollectBus.Protocol.Contracts.Interfaces;
|
using JiShe.CollectBus.Protocol.Contracts.Interfaces;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using JiShe.CollectBus.Common.Consts;
|
using JiShe.CollectBus.Common.Consts;
|
||||||
using JiShe.CollectBus.Common.Enums;
|
using JiShe.CollectBus.Common.Enums;
|
||||||
using System.Diagnostics.Metrics;
|
using System.Diagnostics.Metrics;
|
||||||
|
using JiShe.CollectBus.Common.DeviceBalanceControl;
|
||||||
|
|
||||||
namespace JiShe.CollectBus.Samples;
|
namespace JiShe.CollectBus.Samples;
|
||||||
|
|
||||||
|
|||||||
@ -103,8 +103,12 @@ namespace JiShe.CollectBus.ScheduledMeterReading
|
|||||||
|
|
||||||
//item 为 CacheTasksToBeIssuedKey 对应的缓存待下发的指令生产任务数据Redis Key tempArryay[0]=>CollectBus,tempArryay[1]=>SystemTypeConst,tempArryay[2]=>TaskInfo,tempArryay[3]=>表计类别,tempArryay[4]=>采集频率
|
//item 为 CacheTasksToBeIssuedKey 对应的缓存待下发的指令生产任务数据Redis Key tempArryay[0]=>CollectBus,tempArryay[1]=>SystemTypeConst,tempArryay[2]=>TaskInfo,tempArryay[3]=>表计类别,tempArryay[4]=>采集频率
|
||||||
var tempArryay = item.Split(":");
|
var tempArryay = item.Split(":");
|
||||||
string meteryType = tempArryay[3];//表计类别
|
string meteryType = tempArryay[4];//表计类别
|
||||||
int timeDensity = Convert.ToInt32(tempArryay[4]);//采集频率
|
int timeDensity = Convert.ToInt32(tempArryay[5]);//采集频率
|
||||||
|
if(timeDensity > 15)
|
||||||
|
{
|
||||||
|
timeDensity = 15;
|
||||||
|
}
|
||||||
|
|
||||||
//检查任务时间节点,由于定时任务10秒钟运行一次,需要判定当前时间是否在任务时间节点内,不在则跳过
|
//检查任务时间节点,由于定时任务10秒钟运行一次,需要判定当前时间是否在任务时间节点内,不在则跳过
|
||||||
if (!IsTaskTime(tasksToBeIssueModel.NextTaskTime, timeDensity))
|
if (!IsTaskTime(tasksToBeIssueModel.NextTaskTime, timeDensity))
|
||||||
@ -128,6 +132,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading
|
|||||||
|
|
||||||
if (meteryType == MeterTypeEnum.Ammeter.ToString())
|
if (meteryType == MeterTypeEnum.Ammeter.ToString())
|
||||||
{
|
{
|
||||||
|
var timer = Stopwatch.StartNew();
|
||||||
// 解析结果(结果为嵌套数组)
|
// 解析结果(结果为嵌套数组)
|
||||||
var meterInfos = await GetMeterRedisCacheListData<AmmeterInfo>(oneMinutekeyList, SystemType, ServerTagName, $"{timeDensity}", meterTypes[meteryType]);
|
var meterInfos = await GetMeterRedisCacheListData<AmmeterInfo>(oneMinutekeyList, SystemType, ServerTagName, $"{timeDensity}", meterTypes[meteryType]);
|
||||||
if (meterInfos == null || meterInfos.Count <= 0)
|
if (meterInfos == null || meterInfos.Count <= 0)
|
||||||
@ -137,15 +142,20 @@ namespace JiShe.CollectBus.ScheduledMeterReading
|
|||||||
}
|
}
|
||||||
//await AmmerterScheduledMeterReadingIssued(timeDensity, meterInfos);
|
//await AmmerterScheduledMeterReadingIssued(timeDensity, meterInfos);
|
||||||
|
|
||||||
|
|
||||||
//处理数据
|
//处理数据
|
||||||
await DeviceGroupBalanceControl.ProcessGenericListAsync(
|
//await DeviceGroupBalanceControl.ProcessGenericListAsync(
|
||||||
items: meterInfos,
|
// items: meterInfos,
|
||||||
deviceIdSelector: data => data.FocusAddress,
|
// deviceIdSelector: data => data.FocusAddress,
|
||||||
processor: (data, threadId) =>
|
// processor: (data, threadId) =>
|
||||||
{
|
// {
|
||||||
_= AmmerterCreatePublishTask(timeDensity, data);
|
// _= AmmerterCreatePublishTask(timeDensity, data);
|
||||||
}
|
// }
|
||||||
);
|
//);
|
||||||
|
|
||||||
|
timer.Stop();
|
||||||
|
_logger.LogInformation($"{nameof(CreateToBeIssueTasks)} {timeDensity}分钟采集待下发任务创建完成,{timer.ElapsedMilliseconds},{oneMinutekeyList.Length}");
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (meteryType == MeterTypeEnum.WaterMeter.ToString())
|
else if (meteryType == MeterTypeEnum.WaterMeter.ToString())
|
||||||
{
|
{
|
||||||
@ -758,7 +768,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading
|
|||||||
|
|
||||||
keyValuePairs.TryAdd($"{ammeterInfo.ID}_{tempItem}", meterReadingRecords);
|
keyValuePairs.TryAdd($"{ammeterInfo.ID}_{tempItem}", meterReadingRecords);
|
||||||
}
|
}
|
||||||
await FreeRedisProvider.Instance.HSetAsync(redisCacheKey, keyValuePairs);
|
// await FreeRedisProvider.Instance.HSetAsync(redisCacheKey, keyValuePairs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@ -4,6 +4,7 @@ using System.Threading.Tasks;
|
|||||||
using DotNetCore.CAP;
|
using DotNetCore.CAP;
|
||||||
using JiShe.CollectBus.Ammeters;
|
using JiShe.CollectBus.Ammeters;
|
||||||
using JiShe.CollectBus.Common.Consts;
|
using JiShe.CollectBus.Common.Consts;
|
||||||
|
using JiShe.CollectBus.Common.DeviceBalanceControl;
|
||||||
using JiShe.CollectBus.Common.Helpers;
|
using JiShe.CollectBus.Common.Helpers;
|
||||||
using JiShe.CollectBus.FreeSql;
|
using JiShe.CollectBus.FreeSql;
|
||||||
using JiShe.CollectBus.GatherItem;
|
using JiShe.CollectBus.GatherItem;
|
||||||
|
|||||||
@ -27,14 +27,14 @@ namespace JiShe.CollectBus.Workers
|
|||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
RecurringJobId = nameof(CreateToBeIssueTaskWorker);
|
RecurringJobId = nameof(CreateToBeIssueTaskWorker);
|
||||||
CronExpression = $"{10}/* * * * *";
|
CronExpression = $"*/{1} * * * *";
|
||||||
this._scheduledMeterReadingService = scheduledMeterReadingService;
|
this._scheduledMeterReadingService = scheduledMeterReadingService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public override async Task DoWorkAsync(CancellationToken cancellationToken = new CancellationToken())
|
public override async Task DoWorkAsync(CancellationToken cancellationToken = new CancellationToken())
|
||||||
{
|
{
|
||||||
await _scheduledMeterReadingService.CreateToBeIssueTasks();
|
// await _scheduledMeterReadingService.CreateToBeIssueTasks();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user