修改密码处理

This commit is contained in:
tianfeng 2026-02-12 15:58:21 +08:00
parent 2dedf2e835
commit d21a509001
2 changed files with 191 additions and 1 deletions

View File

@ -24,7 +24,13 @@ public class AccountIsBindCmdExe {
AuthTypeEnum.ACCOUNT.name(),
cmd.requiredReqUserId().toString()
);
return Objects.nonNull(authType);
if (Objects.isNull(authType)) {
return authTypeService.getAuthInfo(
AuthTypeEnum.MOBILE.name(),
cmd.requiredReqUserId().toString()
) != null;
}
return true;
}

View File

@ -2,6 +2,7 @@ import com.red.circle.OtherServiceApplication;
import com.red.circle.component.redis.service.RedisService;
import com.red.circle.order.inner.model.enums.MonthlyRechargeType;
import com.red.circle.other.app.service.activity.ActivityRechargeTicketService;
import com.red.circle.other.infra.database.rds.dao.activity.UserActivityRechargeDAO;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
@ -12,6 +13,9 @@ import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.test.context.junit4.SpringRunner;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
@SpringBootTest(classes = OtherServiceApplication.class)
@ -22,6 +26,14 @@ public class RedisTest {
private RedisTemplate redisTemplate;
@Autowired
private ActivityRechargeTicketService activityRechargeTicketService;
@Autowired
private RedisService redisService;
@Autowired
private UserActivityRechargeDAO userActivityRechargeDAO;
// 常量定义与业务代码保持一致
private static final Long FIXED_ACTIVITY_ID = 2007771533988204877L;
private static final long TICKET_THRESHOLD = 100000L; // 每10000发一张券请根据实际值修改
@Test
public void testRedis(){
@ -56,4 +68,176 @@ public class RedisTest {
}
/**
* 查找脏数据用户ID
* 条件Redis中记录的threshold值 > 数据库中的totalWinCoins
*/
@Test
public void findDirtyDataUsers() {
System.out.println("==========开始查找脏数据用户==========");
System.out.println("活动ID: " + FIXED_ACTIVITY_ID);
System.out.println("券阈值: " + TICKET_THRESHOLD);
System.out.println();
String pattern = String.format("lucky:draw:threshold:*:%s", FIXED_ACTIVITY_ID);
List<Long> dirtyUserIds = new ArrayList<>();
List<String> dirtyDetails = new ArrayList<>();
// 使用 scan 遍历匹配的 key
ScanOptions options = ScanOptions.scanOptions()
.match(pattern)
.count(1000) // 每次扫描1000个
.build();
redisTemplate.execute((RedisCallback<Object>) connection -> {
Cursor<byte[]> cursor = connection.scan(options);
int totalCount = 0;
int dirtyCount = 0;
while (cursor.hasNext()) {
String key = new String(cursor.next());
totalCount++;
try {
// 从key中提取userId
// key格式: lucky:draw:threshold:{userId}:{activityId}
String[] parts = key.split(":");
if (parts.length >= 4) {
Long userId = Long.parseLong(parts[3]);
// 获取Redis中的threshold值
String thresholdStr = redisService.getString(key);
if (thresholdStr == null) {
continue;
}
long redisThreshold = Long.parseLong(thresholdStr);
// 获取数据库中的实际充值总额
BigDecimal totalWinCoins = userActivityRechargeDAO.getUserTotalAmount(
userId, FIXED_ACTIVITY_ID, null);
long dbTotal = (totalWinCoins != null) ? totalWinCoins.longValue() : 0L;
// 检查是否为脏数据Redis中的值 > 数据库中的值
if (redisThreshold > dbTotal) {
dirtyCount++;
dirtyUserIds.add(userId);
String detail = String.format(
"脏数据 #%d - 用户ID: %d, Redis阈值: %d, 数据库总额: %d, 差额: %d",
dirtyCount, userId, redisThreshold, dbTotal, (redisThreshold - dbTotal)
);
dirtyDetails.add(detail);
System.out.println(detail);
}
// 每处理100条打印进度
if (totalCount % 100 == 0) {
System.out.println("已扫描: " + totalCount + " 条记录, 发现脏数据: " + dirtyCount + "");
}
}
} catch (Exception e) {
System.err.println("处理key失败: " + key + ", 错误: " + e.getMessage());
}
}
cursor.close();
System.out.println();
System.out.println("==========扫描完成==========");
System.out.println("总扫描记录数: " + totalCount);
System.out.println("脏数据记录数: " + dirtyCount);
System.out.println();
return null;
});
// 输出汇总结果
if (!dirtyUserIds.isEmpty()) {
System.out.println("==========脏数据用户ID列表==========");
System.out.println(dirtyUserIds);
System.out.println();
System.out.println("==========脏数据详情==========");
for (String detail : dirtyDetails) {
System.out.println(detail);
}
System.out.println();
System.out.println("==========SQL修复语句仅供参考==========");
System.out.println("-- 可以通过以下方式清理Redis中的脏数据:");
for (Long userId : dirtyUserIds) {
String key = String.format("lucky:draw:threshold:%s:%s", userId, FIXED_ACTIVITY_ID);
System.out.println("-- DEL " + key);
}
} else {
System.out.println("未发现脏数据!");
}
}
/**
* 批量修复脏数据慎用
* 将Redis中的threshold值重置为数据库中的实际值
*/
@Test
public void fixDirtyData() {
System.out.println("==========开始修复脏数据==========");
System.out.println("警告此操作将修改Redis数据请确认后执行");
System.out.println();
String pattern = String.format("lucky:draw:threshold:*:%s", FIXED_ACTIVITY_ID);
ScanOptions options = ScanOptions.scanOptions()
.match(pattern)
.count(1000)
.build();
redisTemplate.execute((RedisCallback<Object>) connection -> {
Cursor<byte[]> cursor = connection.scan(options);
int fixedCount = 0;
while (cursor.hasNext()) {
String key = new String(cursor.next());
try {
String[] parts = key.split(":");
if (parts.length >= 4) {
Long userId = Long.parseLong(parts[3]);
String thresholdStr = redisService.getString(key);
if (thresholdStr == null) {
continue;
}
long redisThreshold = Long.parseLong(thresholdStr);
BigDecimal totalWinCoins = userActivityRechargeDAO.getUserTotalAmount(
userId, FIXED_ACTIVITY_ID, null);
long dbTotal = (totalWinCoins != null) ? totalWinCoins.longValue() : 0L;
// 如果是脏数据修复为数据库中的实际值
if (redisThreshold > dbTotal) {
// 计算应该设置的正确threshold值向下取整到阈值倍数
long correctThreshold = 0;
redisService.setString(key, String.valueOf(correctThreshold));
fixedCount++;
System.out.println(String.format(
"已修复 - 用户ID: %d, 原值: %d, 新值: %d, 数据库总额: %d",
userId, redisThreshold, correctThreshold, dbTotal
));
}
}
} catch (Exception e) {
System.err.println("修复key失败: " + key + ", 错误: " + e.getMessage());
}
}
cursor.close();
System.out.println();
System.out.println("==========修复完成==========");
System.out.println("共修复: " + fixedCount + " 条脏数据");
return null;
});
}
}