一个简单的结构用于记录个体下所有商户号的累计金额
背景为:分流所有订单到N个商户个体下的N个商户号中,我需要累计每个商户号的交易金额
private final StringRedisTemplate redisTemplate;
/**
* 添加进Redis存储
* @param merchantGroup 个体名称
* @param merchantId 商户号
* @param amount 金额
*/
public void addTransaction(String merchantGroup, String merchantId, long amount) {
// 使用 Lua 脚本来保证原子性
String script = "local current = redis.call('HGET', KEYS[1], KEYS[2]) " +
"if not current then current = 0 else current = tonumber(current) end " +
"redis.call('HSET', KEYS[1], KEYS[2], current + tonumber(ARGV[1])) " +
"return current + tonumber(ARGV[1])";
RedisScript<Long> redisScript = new DefaultRedisScript<>(script, Long.class);
redisTemplate.execute(redisScript, Arrays.asList(merchantGroup, merchantId), String.valueOf(amount));
// 设置过期时间为 365 天
redisTemplate.expire(merchantGroup, Duration.ofDays(365));
}
这个就是累计各个商户号下的所有的金额统计
这里插入后就是一个个体商户下有多个商户号 每个商户号的一些累计金额
然后通过个体名称获取到该个体下的所有商户号金额汇总
private final StringRedisTemplate redisTemplate;
private final HashOperations<String, String, String> hashOperations;
//获取到个体下边的所有对象
public Map<String, String> getTransactions(String merchantGroup) {
return hashOperations.entries(merchantGroup);
}
/**
* 获取某一个 merchantGroup 下所有商户号的总金额
* @param merchantGroup 个体名称
* @return 总金额
*/
public long getTotalTransactionAmount(String merchantGroup) {
Map<String, String> transactions = getTransactions(merchantGroup);
long totalAmount = 0;
for (String amountStr : transactions.values()) {
totalAmount += Long.parseLong(amountStr);
}
return totalAmount;
}
然后拿到传入集合中在Redis中最小的值的商户号
背景:需要先判断传入的商户号是否在这个Redis中 如果不在则说明新增商户号了,如果都在则说明需要分流订单所以需要选择金额最少的一个出来
/**
* 判断某个商户号是否在Redis中
* @param merchantGroup 个体名称
* @param merchantId 商户号
* @return 是否存在
*/
public boolean isTransactionExist(String merchantGroup, String merchantId) {
return hashOperations.hasKey(merchantGroup, merchantId);
}
/**
* 获取商户号中最小的值
* @param merchantGroup
* @param payInfoVOList 包含商户号的 PayInfoVO 对象列表
* @return
*/
public PayInfoVO getMerchantIdWithMinTransaction(String merchantGroup, List<PayInfoVO> payInfoVOList) {
Map<String, String> transactions = getTransactions(merchantGroup);
PayInfoVO minPayInfoVO = null;
long minAmount = Long.MAX_VALUE;
for (PayInfoVO payInfoVO : payInfoVOList) {
String amountStr = transactions.get(payInfoVO.getMchId());
if (amountStr != null) {
long amount = Long.parseLong(amountStr);
if (amount < minAmount) {
minAmount = amount;
minPayInfoVO = payInfoVO;
}
}
}
minPayInfoVO.setAppIdRemark(merchantGroup);
return minPayInfoVO;
}
/**
* 检查 List<PayInfoVO> 中的商户号是否存在于 Redis 中
* @param remake PayPoolInfo 中的 remake 属性
* @param payInfoVOList 包含商户号的 PayInfoVO 对象列表
* @return 如果所有商户号都在 Redis 中,则返回最小交易金额的 PayInfoVO 对象,否则返回第一个不在 Redis 中的 PayInfoVO 对象
*/
public PayInfoVO checkTransactionsInRedis(String remake, List<PayInfoVO> payInfoVOList) {
for (PayInfoVO payInfoVO : payInfoVOList) {
if (!isTransactionExist(remake, payInfoVO.getMchId())) {
payInfoVO.setAppIdRemark(remake);
return payInfoVO;
}
}
return getMerchantIdWithMinTransaction(remake, payInfoVOList);
}