修改密码处理
This commit is contained in:
parent
2dedf2e835
commit
d21a509001
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -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;
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user