1. Redis实时位置查询概述

Redis实时位置查询是地理位置服务的核心技术,通过Redis的内存级读写性能,可以实现毫秒级的位置查询响应。系统具备实时位置存储、地理索引、范围查询、距离计算、性能优化、监控告警等功能。本文将详细介绍Redis实时位置查询的原理、实现方法、性能优化技巧以及在Java实战中的应用。

1.1 Redis实时位置查询核心价值

  1. 内存级性能: 毫秒级的位置查询响应
  2. 实时性: 支持实时位置更新和查询
  3. 地理索引: 高效的地理位置索引和查询
  4. 高并发: 支持大规模并发位置查询
  5. 可扩展性: 支持集群和分片扩展

1.2 Redis实时位置查询场景

  • 实时定位服务: 实时获取用户或设备位置
  • 地理围栏: 基于地理位置的围栏服务
  • 附近搜索: 查找附近的POI或服务
  • 轨迹追踪: 实时追踪移动目标
  • 位置分析: 基于位置的数据分析

1.3 Redis GEO技术特性

  • GEO命令: Redis 3.2+ 提供的地理位置命令
  • 内存存储: 基于内存的高性能存储
  • 地理索引: 自动创建地理索引
  • 距离计算: 支持多种距离计算算法
  • 范围查询: 支持圆形和矩形范围查询

2. Redis实时位置查询基础实现

2.1 Redis位置查询配置类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
/**
* Redis位置查询配置类
* @author 运维实战
*/
@Configuration
@EnableConfigurationProperties(RedisLocationQueryProperties.class)
public class RedisLocationQueryConfig {

@Autowired
private RedisLocationQueryProperties properties;

/**
* Redis位置查询服务
* @return Redis位置查询服务
*/
@Bean
public RedisLocationQueryService redisLocationQueryService() {
return new RedisLocationQueryService();
}

/**
* Redis位置存储服务
* @return Redis位置存储服务
*/
@Bean
public RedisLocationStorageService redisLocationStorageService() {
return new RedisLocationStorageService();
}

/**
* Redis位置监控服务
* @return Redis位置监控服务
*/
@Bean
public RedisLocationMonitorService redisLocationMonitorService() {
return new RedisLocationMonitorService();
}

private static final Logger logger = LoggerFactory.getLogger(RedisLocationQueryConfig.class);
}

2.2 Redis位置查询属性配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
/**
* Redis位置查询属性配置
* @author 运维实战
*/
@Data
@ConfigurationProperties(prefix = "redis.location")
public class RedisLocationQueryProperties {

/**
* 是否启用Redis位置查询
*/
private boolean enableRedisLocationQuery = true;

/**
* 位置数据键前缀
*/
private String locationKeyPrefix = "location:";

/**
* 用户位置键前缀
*/
private String userLocationKeyPrefix = "user_location:";

/**
* 设备位置键前缀
*/
private String deviceLocationKeyPrefix = "device_location:";

/**
* 位置历史键前缀
*/
private String locationHistoryKeyPrefix = "location_history:";

/**
* 位置数据过期时间(秒)
*/
private long locationExpireTime = 3600;

/**
* 位置历史保留时间(秒)
*/
private long locationHistoryRetentionTime = 86400;

/**
* 默认查询半径(米)
*/
private double defaultQueryRadius = 1000;

/**
* 最大查询半径(米)
*/
private double maxQueryRadius = 10000;

/**
* 是否启用位置缓存
*/
private boolean enableLocationCache = true;

/**
* 位置缓存过期时间(秒)
*/
private long locationCacheExpireTime = 300;

/**
* 是否启用位置压缩
*/
private boolean enableLocationCompression = true;

/**
* 是否启用监控
*/
private boolean enableMonitoring = true;

/**
* 监控间隔(毫秒)
*/
private long monitorInterval = 30000;

/**
* 是否启用告警
*/
private boolean enableAlert = true;

/**
* 查询性能告警阈值(毫秒)
*/
private long queryPerformanceAlertThreshold = 100;

/**
* 存储性能告警阈值(毫秒)
*/
private long storagePerformanceAlertThreshold = 50;
}

2.3 位置数据模型类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
/**
* 位置数据模型类
* @author 运维实战
*/
@Data
public class LocationData {

/**
* 位置ID
*/
private String locationId;

/**
* 用户ID或设备ID
*/
private String objectId;

/**
* 对象类型(user, device, vehicle等)
*/
private String objectType;

/**
* 经度
*/
private Double longitude;

/**
* 纬度
*/
private Double latitude;

/**
* 海拔高度
*/
private Double altitude;

/**
* 精度(米)
*/
private Double accuracy;

/**
* 速度(km/h)
*/
private Double speed;

/**
* 方向角
*/
private Double direction;

/**
* 时间戳
*/
private Long timestamp;

/**
* 是否有效
*/
private Boolean isValid;

/**
* 扩展属性
*/
private Map<String, Object> extendedProperties;

public LocationData() {
this.locationId = UUID.randomUUID().toString();
this.timestamp = System.currentTimeMillis();
this.isValid = true;
this.extendedProperties = new HashMap<>();
}

public LocationData(String objectId, String objectType, Double longitude, Double latitude) {
this();
this.objectId = objectId;
this.objectType = objectType;
this.longitude = longitude;
this.latitude = latitude;
}

/**
* 验证位置数据
* @return 是否有效
*/
public boolean validate() {
if (longitude == null || latitude == null) {
return false;
}

if (longitude < -180 || longitude > 180) {
return false;
}

if (latitude < -90 || latitude > 90) {
return false;
}

if (timestamp == null || timestamp <= 0) {
return false;
}

return true;
}

/**
* 计算两点间距离(米)
* @param other 另一个位置
* @return 距离(米)
*/
public double calculateDistance(LocationData other) {
if (this.longitude == null || this.latitude == null ||
other.longitude == null || other.latitude == null) {
return 0.0;
}

final int R = 6371000; // 地球半径(米)
double lat1Rad = Math.toRadians(this.latitude);
double lat2Rad = Math.toRadians(other.latitude);
double deltaLatRad = Math.toRadians(other.latitude - this.latitude);
double deltaLonRad = Math.toRadians(other.longitude - this.longitude);

double a = Math.sin(deltaLatRad / 2) * Math.sin(deltaLatRad / 2) +
Math.cos(lat1Rad) * Math.cos(lat2Rad) *
Math.sin(deltaLonRad / 2) * Math.sin(deltaLonRad / 2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));

return R * c;
}

/**
* 计算两点间方向角
* @param other 另一个位置
* @return 方向角(度)
*/
public double calculateBearing(LocationData other) {
if (this.longitude == null || this.latitude == null ||
other.longitude == null || other.latitude == null) {
return 0.0;
}

double lat1Rad = Math.toRadians(this.latitude);
double lat2Rad = Math.toRadians(other.latitude);
double deltaLonRad = Math.toRadians(other.longitude - this.longitude);

double y = Math.sin(deltaLonRad) * Math.cos(lat2Rad);
double x = Math.cos(lat1Rad) * Math.sin(lat2Rad) -
Math.sin(lat1Rad) * Math.cos(lat2Rad) * Math.cos(deltaLonRad);

double bearing = Math.toDegrees(Math.atan2(y, x));
return (bearing + 360) % 360;
}

/**
* 添加扩展属性
* @param key 键
* @param value 值
*/
public void addExtendedProperty(String key, Object value) {
if (extendedProperties == null) {
extendedProperties = new HashMap<>();
}
extendedProperties.put(key, value);
}

/**
* 获取扩展属性
* @param key 键
* @return
*/
public Object getExtendedProperty(String key) {
return extendedProperties != null ? extendedProperties.get(key) : null;
}
}

2.4 基础Redis位置查询服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
/**
* 基础Redis位置查询服务
* @author 运维实战
*/
@Service
public class RedisLocationQueryService {

@Autowired
private RedisLocationQueryProperties properties;

@Autowired
private RedisTemplate<String, Object> redisTemplate;

@Autowired
private RedisLocationStorageService redisLocationStorageService;

@Autowired
private RedisLocationMonitorService redisLocationMonitorService;

private static final Logger logger = LoggerFactory.getLogger(RedisLocationQueryService.class);

/**
* 存储位置数据
* @param locationData 位置数据
* @return 存储结果
*/
public RedisLocationStorageResult storeLocationData(LocationData locationData) {
logger.info("存储位置数据,对象ID: {}, 经度: {}, 纬度: {}",
locationData.getObjectId(), locationData.getLongitude(), locationData.getLatitude());

RedisLocationStorageResult result = new RedisLocationStorageResult();
result.setObjectId(locationData.getObjectId());
result.setStartTime(System.currentTimeMillis());

try {
// 验证位置数据
if (!locationData.validate()) {
result.setSuccess(false);
result.setError("位置数据验证失败");
result.setEndTime(System.currentTimeMillis());
return result;
}

// 存储位置数据
result = redisLocationStorageService.storeLocationData(locationData);

// 记录存储指标
redisLocationMonitorService.recordLocationStorage(locationData.getObjectId(), true);

logger.info("位置数据存储完成,对象ID: {}, 成功: {}, 耗时: {}ms",
locationData.getObjectId(), result.isSuccess(), result.getDuration());

return result;

} catch (Exception e) {
logger.error("位置数据存储异常,对象ID: {}", locationData.getObjectId(), e);
result.setSuccess(false);
result.setError("位置数据存储异常: " + e.getMessage());
result.setEndTime(System.currentTimeMillis());

// 记录存储失败指标
redisLocationMonitorService.recordLocationStorage(locationData.getObjectId(), false);

return result;
}
}

/**
* 查询附近位置
* @param longitude 经度
* @param latitude 纬度
* @param radius 半径(米)
* @param objectType 对象类型
* @return 查询结果
*/
public RedisLocationQueryResult queryNearbyLocations(Double longitude, Double latitude,
Double radius, String objectType) {
logger.info("查询附近位置,中心点: ({}, {}), 半径: {}m, 对象类型: {}",
longitude, latitude, radius, objectType);

RedisLocationQueryResult result = new RedisLocationQueryResult();
result.setLongitude(longitude);
result.setLatitude(latitude);
result.setRadius(radius);
result.setStartTime(System.currentTimeMillis());

try {
// 验证查询参数
if (longitude == null || latitude == null || radius == null) {
result.setSuccess(false);
result.setError("查询参数不能为空");
result.setEndTime(System.currentTimeMillis());
return result;
}

// 限制查询半径
if (radius > properties.getMaxQueryRadius()) {
radius = properties.getMaxQueryRadius();
}

// 执行附近位置查询
result = redisLocationStorageService.queryNearbyLocations(longitude, latitude, radius, objectType);

// 记录查询指标
redisLocationMonitorService.recordLocationQuery(longitude, latitude, result.getLocationDataList().size(), true);

logger.info("附近位置查询完成,中心点: ({}, {}), 结果数量: {}, 耗时: {}ms",
longitude, latitude, result.getLocationDataList().size(), result.getDuration());

return result;

} catch (Exception e) {
logger.error("附近位置查询异常,中心点: ({}, {})", longitude, latitude, e);
result.setSuccess(false);
result.setError("附近位置查询异常: " + e.getMessage());
result.setEndTime(System.currentTimeMillis());

// 记录查询失败指标
redisLocationMonitorService.recordLocationQuery(longitude, latitude, 0, false);

return result;
}
}

/**
* 获取对象当前位置
* @param objectId 对象ID
* @return 位置数据
*/
public RedisLocationQueryResult getCurrentLocation(String objectId) {
logger.info("获取对象当前位置,对象ID: {}", objectId);

RedisLocationQueryResult result = new RedisLocationQueryResult();
result.setObjectId(objectId);
result.setStartTime(System.currentTimeMillis());

try {
// 执行当前位置查询
result = redisLocationStorageService.getCurrentLocation(objectId);

// 记录查询指标
redisLocationMonitorService.recordLocationQuery(0.0, 0.0, result.getLocationDataList().size(), true);

logger.info("当前位置查询完成,对象ID: {}, 结果数量: {}, 耗时: {}ms",
objectId, result.getLocationDataList().size(), result.getDuration());

return result;

} catch (Exception e) {
logger.error("当前位置查询异常,对象ID: {}", objectId, e);
result.setSuccess(false);
result.setError("当前位置查询异常: " + e.getMessage());
result.setEndTime(System.currentTimeMillis());

// 记录查询失败指标
redisLocationMonitorService.recordLocationQuery(0.0, 0.0, 0, false);

return result;
}
}

/**
* 计算两点间距离
* @param longitude1 经度1
* @param latitude1 纬度1
* @param longitude2 经度2
* @param latitude2 纬度2
* @return 距离(米)
*/
public double calculateDistance(Double longitude1, Double latitude1,
Double longitude2, Double latitude2) {
logger.info("计算两点间距离,点1: ({}, {}), 点2: ({}, {})",
longitude1, latitude1, longitude2, latitude2);

try {
// 使用Redis GEO命令计算距离
String key = properties.getLocationKeyPrefix() + "distance_calc";

// 添加两个点到临时键
redisTemplate.opsForGeo().add(key, new Point(longitude1, latitude1), "point1");
redisTemplate.opsForGeo().add(key, new Point(longitude2, latitude2), "point2");

// 计算距离
Distance distance = redisTemplate.opsForGeo().distance(key, "point1", "point2", Metrics.KILOMETERS);

// 删除临时键
redisTemplate.delete(key);

double distanceInMeters = distance.getValue() * 1000;

logger.info("距离计算完成,距离: {}m", distanceInMeters);

return distanceInMeters;

} catch (Exception e) {
logger.error("距离计算异常", e);
return 0.0;
}
}
}

2.5 Redis位置查询结果类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
/**
* Redis位置存储结果类
* @author 运维实战
*/
@Data
public class RedisLocationStorageResult {

private boolean success;
private String objectId;
private LocationData storedData;
private String error;
private long startTime;
private long endTime;

public RedisLocationStorageResult() {
this.success = false;
}

/**
* 获取存储耗时
* @return 存储耗时(毫秒)
*/
public long getDuration() {
return endTime - startTime;
}

/**
* 是否成功
* @return 是否成功
*/
public boolean isSuccess() {
return success;
}
}

/**
* Redis位置查询结果类
* @author 运维实战
*/
@Data
public class RedisLocationQueryResult {

private boolean success;
private String objectId;
private Double longitude;
private Double latitude;
private Double radius;
private List<LocationData> locationDataList;
private String error;
private long startTime;
private long endTime;

public RedisLocationQueryResult() {
this.success = false;
this.locationDataList = new ArrayList<>();
}

/**
* 获取查询耗时
* @return 查询耗时(毫秒)
*/
public long getDuration() {
return endTime - startTime;
}

/**
* 是否成功
* @return 是否成功
*/
public boolean isSuccess() {
return success;
}
}

3. 高级功能实现

3.1 Redis位置存储服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
/**
* Redis位置存储服务
* @author 运维实战
*/
@Service
public class RedisLocationStorageService {

@Autowired
private RedisLocationQueryProperties properties;

@Autowired
private RedisTemplate<String, Object> redisTemplate;

@Autowired
private RedisLocationMonitorService redisLocationMonitorService;

private static final Logger logger = LoggerFactory.getLogger(RedisLocationStorageService.class);

/**
* 存储位置数据
* @param locationData 位置数据
* @return 存储结果
*/
public RedisLocationStorageResult storeLocationData(LocationData locationData) {
logger.info("存储位置数据到Redis,对象ID: {}", locationData.getObjectId());

RedisLocationStorageResult result = new RedisLocationStorageResult();
result.setObjectId(locationData.getObjectId());
result.setStartTime(System.currentTimeMillis());

try {
// 生成位置键
String locationKey = generateLocationKey(locationData.getObjectId(), locationData.getObjectType());

// 使用Redis GEO命令存储位置
redisTemplate.opsForGeo().add(locationKey,
new Point(locationData.getLongitude(), locationData.getLatitude()),
locationData.getObjectId());

// 设置过期时间
redisTemplate.expire(locationKey, Duration.ofSeconds(properties.getLocationExpireTime()));

// 存储位置详细信息
String detailKey = locationKey + ":detail:" + locationData.getObjectId();
redisTemplate.opsForValue().set(detailKey, locationData,
Duration.ofSeconds(properties.getLocationExpireTime()));

// 存储位置历史
storeLocationHistory(locationData);

result.setSuccess(true);
result.setStoredData(locationData);
result.setEndTime(System.currentTimeMillis());

logger.info("位置数据存储到Redis成功,对象ID: {}, 耗时: {}ms",
locationData.getObjectId(), result.getDuration());

return result;

} catch (Exception e) {
logger.error("位置数据存储到Redis失败,对象ID: {}", locationData.getObjectId(), e);
result.setSuccess(false);
result.setError("位置数据存储到Redis失败: " + e.getMessage());
result.setEndTime(System.currentTimeMillis());
return result;
}
}

/**
* 查询附近位置
* @param longitude 经度
* @param latitude 纬度
* @param radius 半径(米)
* @param objectType 对象类型
* @return 查询结果
*/
public RedisLocationQueryResult queryNearbyLocations(Double longitude, Double latitude,
Double radius, String objectType) {
logger.info("查询附近位置,中心点: ({}, {}), 半径: {}m", longitude, latitude, radius);

RedisLocationQueryResult result = new RedisLocationQueryResult();
result.setLongitude(longitude);
result.setLatitude(latitude);
result.setRadius(radius);
result.setStartTime(System.currentTimeMillis());

try {
// 生成位置键
String locationKey = generateLocationKey(null, objectType);

// 使用Redis GEO命令查询附近位置
Circle circle = new Circle(new Point(longitude, latitude), new Distance(radius, Metrics.METERS));
GeoResults<RedisGeoCommands.GeoLocation<Object>> geoResults =
redisTemplate.opsForGeo().radius(locationKey, circle);

List<LocationData> locationDataList = new ArrayList<>();

for (GeoResult<RedisGeoCommands.GeoLocation<Object>> geoResult : geoResults) {
String objectId = geoResult.getContent().getName().toString();
Distance distance = geoResult.getDistance();

// 获取位置详细信息
LocationData locationData = getLocationDetail(objectId, objectType);
if (locationData != null) {
locationData.addExtendedProperty("distance", distance.getValue());
locationDataList.add(locationData);
}
}

result.setSuccess(true);
result.setLocationDataList(locationDataList);
result.setEndTime(System.currentTimeMillis());

logger.info("附近位置查询成功,中心点: ({}, {}), 结果数量: {}, 耗时: {}ms",
longitude, latitude, locationDataList.size(), result.getDuration());

return result;

} catch (Exception e) {
logger.error("附近位置查询失败,中心点: ({}, {})", longitude, latitude, e);
result.setSuccess(false);
result.setError("附近位置查询失败: " + e.getMessage());
result.setEndTime(System.currentTimeMillis());
return result;
}
}

/**
* 获取对象当前位置
* @param objectId 对象ID
* @return 位置数据
*/
public RedisLocationQueryResult getCurrentLocation(String objectId) {
logger.info("获取对象当前位置,对象ID: {}", objectId);

RedisLocationQueryResult result = new RedisLocationQueryResult();
result.setObjectId(objectId);
result.setStartTime(System.currentTimeMillis());

try {
// 获取位置详细信息
LocationData locationData = getLocationDetail(objectId, null);

List<LocationData> locationDataList = new ArrayList<>();
if (locationData != null) {
locationDataList.add(locationData);
}

result.setSuccess(true);
result.setLocationDataList(locationDataList);
result.setEndTime(System.currentTimeMillis());

logger.info("当前位置查询成功,对象ID: {}, 结果数量: {}, 耗时: {}ms",
objectId, locationDataList.size(), result.getDuration());

return result;

} catch (Exception e) {
logger.error("当前位置查询失败,对象ID: {}", objectId, e);
result.setSuccess(false);
result.setError("当前位置查询失败: " + e.getMessage());
result.setEndTime(System.currentTimeMillis());
return result;
}
}

/**
* 存储位置历史
* @param locationData 位置数据
*/
private void storeLocationHistory(LocationData locationData) {
try {
String historyKey = properties.getLocationHistoryKeyPrefix() + locationData.getObjectId();

// 使用有序集合存储位置历史
redisTemplate.opsForZSet().add(historyKey, locationData, locationData.getTimestamp().doubleValue());

// 设置过期时间
redisTemplate.expire(historyKey, Duration.ofSeconds(properties.getLocationHistoryRetentionTime()));

// 限制历史记录数量
redisTemplate.opsForZSet().removeRange(historyKey, 0, -1001);

} catch (Exception e) {
logger.error("存储位置历史失败,对象ID: {}", locationData.getObjectId(), e);
}
}

/**
* 获取位置详细信息
* @param objectId 对象ID
* @param objectType 对象类型
* @return 位置数据
*/
private LocationData getLocationDetail(String objectId, String objectType) {
try {
String locationKey = generateLocationKey(objectId, objectType);
String detailKey = locationKey + ":detail:" + objectId;

Object detail = redisTemplate.opsForValue().get(detailKey);
if (detail instanceof LocationData) {
return (LocationData) detail;
}

return null;

} catch (Exception e) {
logger.error("获取位置详细信息失败,对象ID: {}", objectId, e);
return null;
}
}

/**
* 生成位置键
* @param objectId 对象ID
* @param objectType 对象类型
* @return 位置键
*/
private String generateLocationKey(String objectId, String objectType) {
if (objectType != null) {
switch (objectType.toLowerCase()) {
case "user":
return properties.getUserLocationKeyPrefix() + (objectId != null ? objectId : "all");
case "device":
return properties.getDeviceLocationKeyPrefix() + (objectId != null ? objectId : "all");
default:
return properties.getLocationKeyPrefix() + objectType + ":" + (objectId != null ? objectId : "all");
}
}
return properties.getLocationKeyPrefix() + (objectId != null ? objectId : "all");
}
}

3.2 Redis位置监控服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
/**
* Redis位置监控服务
* @author 运维实战
*/
@Service
public class RedisLocationMonitorService {

private final AtomicLong totalLocationStored = new AtomicLong(0);
private final AtomicLong totalLocationQueried = new AtomicLong(0);
private final AtomicLong totalSuccessfulStorages = new AtomicLong(0);
private final AtomicLong totalFailedStorages = new AtomicLong(0);
private final AtomicLong totalSuccessfulQueries = new AtomicLong(0);
private final AtomicLong totalFailedQueries = new AtomicLong(0);

private long lastResetTime = System.currentTimeMillis();
private final long resetInterval = 300000; // 5分钟重置一次

private static final Logger logger = LoggerFactory.getLogger(RedisLocationMonitorService.class);

/**
* 记录位置存储
* @param objectId 对象ID
* @param success 是否成功
*/
public void recordLocationStorage(String objectId, boolean success) {
totalLocationStored.incrementAndGet();

if (success) {
totalSuccessfulStorages.incrementAndGet();
} else {
totalFailedStorages.incrementAndGet();
}

logger.debug("记录位置存储: 对象ID={}, 成功={}", objectId, success);
}

/**
* 记录位置查询
* @param longitude 经度
* @param latitude 纬度
* @param resultCount 结果数量
* @param success 是否成功
*/
public void recordLocationQuery(Double longitude, Double latitude, int resultCount, boolean success) {
totalLocationQueried.incrementAndGet();

if (success) {
totalSuccessfulQueries.incrementAndGet();
} else {
totalFailedQueries.incrementAndGet();
}

logger.debug("记录位置查询: 经度={}, 纬度={}, 结果数量={}, 成功={}", longitude, latitude, resultCount, success);
}

/**
* 获取监控指标
* @return 监控指标
*/
public RedisLocationMetrics getMetrics() {
// 检查是否需要重置
if (System.currentTimeMillis() - lastResetTime > resetInterval) {
resetMetrics();
}

RedisLocationMetrics metrics = new RedisLocationMetrics();
metrics.setTotalLocationStored(totalLocationStored.get());
metrics.setTotalLocationQueried(totalLocationQueried.get());
metrics.setTotalSuccessfulStorages(totalSuccessfulStorages.get());
metrics.setTotalFailedStorages(totalFailedStorages.get());
metrics.setTotalSuccessfulQueries(totalSuccessfulQueries.get());
metrics.setTotalFailedQueries(totalFailedQueries.get());
metrics.setTimestamp(System.currentTimeMillis());

return metrics;
}

/**
* 重置指标
*/
private void resetMetrics() {
totalLocationStored.set(0);
totalLocationQueried.set(0);
totalSuccessfulStorages.set(0);
totalFailedStorages.set(0);
totalSuccessfulQueries.set(0);
totalFailedQueries.set(0);
lastResetTime = System.currentTimeMillis();

logger.info("Redis位置监控指标重置");
}

/**
* 定期监控Redis位置查询状态
*/
@Scheduled(fixedRate = 30000) // 每30秒监控一次
public void monitorRedisLocationQueryStatus() {
try {
RedisLocationMetrics metrics = getMetrics();

logger.info("Redis位置查询监控: 存储={}, 查询={}, 存储成功={}, 存储失败={}, 查询成功={}, 查询失败={}, 存储成功率={}%, 查询成功率={}%",
metrics.getTotalLocationStored(), metrics.getTotalLocationQueried(),
metrics.getTotalSuccessfulStorages(), metrics.getTotalFailedStorages(),
metrics.getTotalSuccessfulQueries(), metrics.getTotalFailedQueries(),
String.format("%.2f", metrics.getStorageSuccessRate()),
String.format("%.2f", metrics.getQuerySuccessRate()));

// 检查异常情况
if (metrics.getStorageSuccessRate() < 95) {
logger.warn("Redis位置存储成功率过低: {}%", String.format("%.2f", metrics.getStorageSuccessRate()));
}

if (metrics.getQuerySuccessRate() < 90) {
logger.warn("Redis位置查询成功率过低: {}%", String.format("%.2f", metrics.getQuerySuccessRate()));
}

} catch (Exception e) {
logger.error("Redis位置查询状态监控失败", e);
}
}
}

3.3 Redis位置指标类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
/**
* Redis位置指标类
* @author 运维实战
*/
@Data
public class RedisLocationMetrics {

private long totalLocationStored;
private long totalLocationQueried;
private long totalSuccessfulStorages;
private long totalFailedStorages;
private long totalSuccessfulQueries;
private long totalFailedQueries;
private long timestamp;

public RedisLocationMetrics() {
this.timestamp = System.currentTimeMillis();
}

/**
* 获取存储成功率
* @return 存储成功率
*/
public double getStorageSuccessRate() {
long total = totalSuccessfulStorages + totalFailedStorages;
if (total == 0) return 0.0;
return (double) totalSuccessfulStorages / total * 100;
}

/**
* 获取存储失败率
* @return 存储失败率
*/
public double getStorageFailureRate() {
long total = totalSuccessfulStorages + totalFailedStorages;
if (total == 0) return 0.0;
return (double) totalFailedStorages / total * 100;
}

/**
* 获取查询成功率
* @return 查询成功率
*/
public double getQuerySuccessRate() {
long total = totalSuccessfulQueries + totalFailedQueries;
if (total == 0) return 0.0;
return (double) totalSuccessfulQueries / total * 100;
}

/**
* 获取查询失败率
* @return 查询失败率
*/
public double getQueryFailureRate() {
long total = totalSuccessfulQueries + totalFailedQueries;
if (total == 0) return 0.0;
return (double) totalFailedQueries / total * 100;
}

/**
* 获取存储效率
* @return 存储效率
*/
public double getStorageEfficiency() {
if (totalLocationStored == 0) return 0.0;
return (double) totalSuccessfulStorages / totalLocationStored * 100;
}

/**
* 获取查询效率
* @return 查询效率
*/
public double getQueryEfficiency() {
if (totalLocationQueried == 0) return 0.0;
return (double) totalSuccessfulQueries / totalLocationQueried * 100;
}

/**
* 是否健康
* @return 是否健康
*/
public boolean isHealthy() {
return getStorageSuccessRate() > 95 && getQuerySuccessRate() > 90;
}
}

4. Redis位置查询控制器

4.1 Redis位置查询REST控制器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/**
* Redis位置查询REST控制器
* @author 运维实战
*/
@RestController
@RequestMapping("/api/redis/location")
public class RedisLocationQueryController {

@Autowired
private RedisLocationQueryService redisLocationQueryService;

@Autowired
private RedisLocationMonitorService redisLocationMonitorService;

private static final Logger logger = LoggerFactory.getLogger(RedisLocationQueryController.class);

/**
* 存储位置数据
* @param locationData 位置数据
* @return 存储结果
*/
@PostMapping("/store")
public ResponseEntity<RedisLocationStorageResult> storeLocationData(@RequestBody LocationData locationData) {
try {
logger.info("接收到位置数据存储请求,对象ID: {}", locationData.getObjectId());

RedisLocationStorageResult result = redisLocationQueryService.storeLocationData(locationData);

return ResponseEntity.ok(result);

} catch (Exception e) {
logger.error("位置数据存储失败", e);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
}
}

/**
* 查询附近位置
* @param longitude 经度
* @param latitude 纬度
* @param radius 半径(米)
* @param objectType 对象类型
* @return 查询结果
*/
@GetMapping("/nearby")
public ResponseEntity<RedisLocationQueryResult> queryNearbyLocations(
@RequestParam Double longitude,
@RequestParam Double latitude,
@RequestParam(defaultValue = "1000") Double radius,
@RequestParam(required = false) String objectType) {
try {
logger.info("接收到附近位置查询请求,中心点: ({}, {}), 半径: {}m", longitude, latitude, radius);

RedisLocationQueryResult result = redisLocationQueryService.queryNearbyLocations(
longitude, latitude, radius, objectType);

return ResponseEntity.ok(result);

} catch (Exception e) {
logger.error("附近位置查询失败", e);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
}
}

/**
* 获取对象当前位置
* @param objectId 对象ID
* @return 位置数据
*/
@GetMapping("/current/{objectId}")
public ResponseEntity<RedisLocationQueryResult> getCurrentLocation(@PathVariable String objectId) {
try {
logger.info("接收到当前位置查询请求,对象ID: {}", objectId);

RedisLocationQueryResult result = redisLocationQueryService.getCurrentLocation(objectId);

return ResponseEntity.ok(result);

} catch (Exception e) {
logger.error("当前位置查询失败", e);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
}
}

/**
* 计算两点间距离
* @param longitude1 经度1
* @param latitude1 纬度1
* @param longitude2 经度2
* @param latitude2 纬度2
* @return 距离(米)
*/
@GetMapping("/distance")
public ResponseEntity<Map<String, Object>> calculateDistance(
@RequestParam Double longitude1,
@RequestParam Double latitude1,
@RequestParam Double longitude2,
@RequestParam Double latitude2) {
try {
logger.info("接收到距离计算请求,点1: ({}, {}), 点2: ({}, {})",
longitude1, latitude1, longitude2, latitude2);

double distance = redisLocationQueryService.calculateDistance(
longitude1, latitude1, longitude2, latitude2);

Map<String, Object> response = new HashMap<>();
response.put("distance", distance);
response.put("unit", "meters");
response.put("timestamp", System.currentTimeMillis());

return ResponseEntity.ok(response);

} catch (Exception e) {
logger.error("距离计算失败", e);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
}
}

/**
* 获取Redis位置查询监控指标
* @return 监控指标
*/
@GetMapping("/metrics")
public ResponseEntity<RedisLocationMetrics> getRedisLocationMetrics() {
try {
RedisLocationMetrics metrics = redisLocationMonitorService.getMetrics();
return ResponseEntity.ok(metrics);
} catch (Exception e) {
logger.error("获取Redis位置查询监控指标失败", e);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
}
}
}

5. Redis位置查询注解和AOP

5.1 Redis位置查询注解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
/**
* Redis位置查询注解
* @author 运维实战
*/
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RedisLocationQuery {

/**
* 对象ID
*/
String objectId() default "";

/**
* 操作类型
*/
String operationType() default "STORE";

/**
* 是否启用Redis位置查询
*/
boolean enableRedisLocationQuery() default true;

/**
* 是否启用位置缓存
*/
boolean enableLocationCache() default true;

/**
* 是否启用位置压缩
*/
boolean enableLocationCompression() default true;

/**
* 是否启用监控
*/
boolean enableMonitoring() default true;

/**
* 操作失败时的消息
*/
String message() default "Redis位置查询操作失败,请稍后重试";

/**
* 操作失败时的HTTP状态码
*/
int statusCode() default 500;
}

5.2 Redis位置查询AOP切面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
/**
* Redis位置查询AOP切面
* @author 运维实战
*/
@Aspect
@Component
public class RedisLocationQueryAspect {

@Autowired
private RedisLocationMonitorService redisLocationMonitorService;

private static final Logger logger = LoggerFactory.getLogger(RedisLocationQueryAspect.class);

/**
* Redis位置查询切点
*/
@Pointcut("@annotation(redisLocationQuery)")
public void redisLocationQueryPointcut(RedisLocationQuery redisLocationQuery) {}

/**
* Redis位置查询环绕通知
* @param joinPoint 连接点
* @param redisLocationQuery Redis位置查询注解
* @return 执行结果
* @throws Throwable 异常
*/
@Around("redisLocationQueryPointcut(redisLocationQuery)")
public Object around(ProceedingJoinPoint joinPoint, RedisLocationQuery redisLocationQuery) throws Throwable {
String methodName = joinPoint.getSignature().getName();

try {
// 获取方法参数
Object[] args = joinPoint.getArgs();

// 查找对象ID参数
String objectId = redisLocationQuery.objectId();
String operationType = redisLocationQuery.operationType();

if (objectId != null && !objectId.isEmpty()) {
logger.info("Redis位置查询操作开始: method={}, objectId={}, operationType={}",
methodName, objectId, operationType);

// 记录Redis位置查询操作指标
if ("STORE".equals(operationType)) {
redisLocationMonitorService.recordLocationStorage(objectId, true);
} else if ("QUERY".equals(operationType)) {
redisLocationMonitorService.recordLocationQuery(0.0, 0.0, 0, true);
}
}

// 执行原方法
return joinPoint.proceed();

} catch (Exception e) {
logger.error("Redis位置查询操作异常: method={}", methodName, e);
throw new RedisLocationQueryException(redisLocationQuery.message(), redisLocationQuery.statusCode());
}
}
}

5.3 Redis位置查询异常类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/**
* Redis位置查询异常类
* @author 运维实战
*/
public class RedisLocationQueryException extends RuntimeException {

private final int statusCode;

public RedisLocationQueryException(String message) {
super(message);
this.statusCode = 500;
}

public RedisLocationQueryException(String message, int statusCode) {
super(message);
this.statusCode = statusCode;
}

public RedisLocationQueryException(String message, Throwable cause) {
super(message, cause);
this.statusCode = 500;
}

public RedisLocationQueryException(String message, Throwable cause, int statusCode) {
super(message, cause);
this.statusCode = statusCode;
}

public int getStatusCode() {
return statusCode;
}
}

5.4 Redis位置查询异常处理器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/**
* Redis位置查询异常处理器
* @author 运维实战
*/
@ControllerAdvice
public class RedisLocationQueryExceptionHandler {

private static final Logger logger = LoggerFactory.getLogger(RedisLocationQueryExceptionHandler.class);

/**
* 处理Redis位置查询异常
* @param e 异常
* @return 错误响应
*/
@ExceptionHandler(RedisLocationQueryException.class)
public ResponseEntity<Map<String, Object>> handleRedisLocationQueryException(RedisLocationQueryException e) {
logger.warn("Redis位置查询异常: {}", e.getMessage());

Map<String, Object> response = new HashMap<>();
response.put("error", "REDIS_LOCATION_QUERY_FAILED");
response.put("message", e.getMessage());
response.put("timestamp", System.currentTimeMillis());

return ResponseEntity.status(e.getStatusCode()).body(response);
}
}

6. 实际应用示例

6.1 使用Redis位置查询注解的服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
/**
* 使用Redis位置查询注解的服务
* @author 运维实战
*/
@Service
public class RedisLocationQueryExampleService {

private static final Logger logger = LoggerFactory.getLogger(RedisLocationQueryExampleService.class);

/**
* 基础Redis位置查询存储示例
* @param locationData 位置数据
* @return 处理结果
*/
@RedisLocationQuery(objectId = "test_object", operationType = "STORE",
enableRedisLocationQuery = true, enableLocationCache = true,
enableLocationCompression = true, enableMonitoring = true,
message = "基础Redis位置查询存储:操作失败")
public String basicRedisLocationQueryStorage(LocationData locationData) {
logger.info("执行基础Redis位置查询存储示例,对象ID: {}", locationData.getObjectId());

// 模拟Redis位置查询存储操作
try {
Thread.sleep(50);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}

return "基础Redis位置查询存储完成,对象ID: " + locationData.getObjectId();
}

/**
* 高性能Redis位置查询示例
* @param locationDataList 位置数据列表
* @return 处理结果
*/
@RedisLocationQuery(objectId = "batch_object", operationType = "STORE",
enableRedisLocationQuery = true, enableLocationCache = true,
enableLocationCompression = true, enableMonitoring = true,
message = "高性能Redis位置查询:操作失败")
public String highPerformanceRedisLocationQuery(List<LocationData> locationDataList) {
logger.info("执行高性能Redis位置查询示例,数量: {}", locationDataList.size());

// 模拟高性能Redis位置查询操作
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}

return "高性能Redis位置查询完成,数量: " + locationDataList.size();
}

/**
* 实时位置查询示例
* @param longitude 经度
* @param latitude 纬度
* @param radius 半径
* @return 处理结果
*/
@RedisLocationQuery(objectId = "query_object", operationType = "QUERY",
enableRedisLocationQuery = true, enableLocationCache = true,
enableLocationCompression = true, enableMonitoring = true,
message = "实时位置查询:操作失败")
public String realTimeLocationQuery(Double longitude, Double latitude, Double radius) {
logger.info("执行实时位置查询示例,中心点: ({}, {}), 半径: {}m", longitude, latitude, radius);

// 模拟实时位置查询操作
try {
Thread.sleep(30);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}

return "实时位置查询完成,中心点: (" + longitude + ", " + latitude + "), 半径: " + radius + "m";
}
}

6.2 Redis位置查询测试控制器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
/**
* Redis位置查询测试控制器
* @author 运维实战
*/
@RestController
@RequestMapping("/api/redis/location/test")
public class RedisLocationQueryTestController {

@Autowired
private RedisLocationQueryExampleService exampleService;

@Autowired
private RedisLocationQueryService redisLocationQueryService;

@Autowired
private RedisLocationMonitorService redisLocationMonitorService;

private static final Logger logger = LoggerFactory.getLogger(RedisLocationQueryTestController.class);

/**
* 基础Redis位置查询存储测试
* @param objectId 对象ID
* @return 测试结果
*/
@GetMapping("/basic")
public ResponseEntity<Map<String, String>> testBasicRedisLocationQueryStorage(@RequestParam String objectId) {
try {
// 生成测试位置数据
LocationData locationData = generateTestLocationData(objectId);

String result = exampleService.basicRedisLocationQueryStorage(locationData);

Map<String, String> response = new HashMap<>();
response.put("status", "SUCCESS");
response.put("result", result);
response.put("timestamp", String.valueOf(System.currentTimeMillis()));

return ResponseEntity.ok(response);

} catch (RedisLocationQueryException e) {
logger.warn("基础Redis位置查询存储测试失败: {}", e.getMessage());
return ResponseEntity.status(e.getStatusCode()).build();
} catch (Exception e) {
logger.error("基础Redis位置查询存储测试失败", e);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
}
}

/**
* 高性能Redis位置查询测试
* @param objectId 对象ID
* @param count 数量
* @return 测试结果
*/
@GetMapping("/high-performance")
public ResponseEntity<Map<String, String>> testHighPerformanceRedisLocationQuery(
@RequestParam String objectId, @RequestParam int count) {
try {
// 生成测试位置数据列表
List<LocationData> locationDataList = generateTestLocationDataList(objectId, count);

String result = exampleService.highPerformanceRedisLocationQuery(locationDataList);

Map<String, String> response = new HashMap<>();
response.put("status", "SUCCESS");
response.put("result", result);
response.put("timestamp", String.valueOf(System.currentTimeMillis()));

return ResponseEntity.ok(response);

} catch (RedisLocationQueryException e) {
logger.warn("高性能Redis位置查询测试失败: {}", e.getMessage());
return ResponseEntity.status(e.getStatusCode()).build();
} catch (Exception e) {
logger.error("高性能Redis位置查询测试失败", e);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
}
}

/**
* 实时位置查询测试
* @param longitude 经度
* @param latitude 纬度
* @param radius 半径
* @return 测试结果
*/
@GetMapping("/real-time")
public ResponseEntity<Map<String, String>> testRealTimeLocationQuery(
@RequestParam Double longitude,
@RequestParam Double latitude,
@RequestParam(defaultValue = "1000") Double radius) {
try {
String result = exampleService.realTimeLocationQuery(longitude, latitude, radius);

Map<String, String> response = new HashMap<>();
response.put("status", "SUCCESS");
response.put("result", result);
response.put("timestamp", String.valueOf(System.currentTimeMillis()));

return ResponseEntity.ok(response);

} catch (RedisLocationQueryException e) {
logger.warn("实时位置查询测试失败: {}", e.getMessage());
return ResponseEntity.status(e.getStatusCode()).build();
} catch (Exception e) {
logger.error("实时位置查询测试失败", e);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
}
}

/**
* 获取Redis位置查询监控指标
* @return Redis位置查询监控指标
*/
@GetMapping("/metrics")
public ResponseEntity<RedisLocationMetrics> getRedisLocationMetrics() {
try {
RedisLocationMetrics metrics = redisLocationMonitorService.getMetrics();
return ResponseEntity.ok(metrics);
} catch (Exception e) {
logger.error("获取Redis位置查询监控指标失败", e);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
}
}

/**
* 生成测试位置数据
* @param objectId 对象ID
* @return 测试位置数据
*/
private LocationData generateTestLocationData(String objectId) {
LocationData locationData = new LocationData();
locationData.setObjectId(objectId);
locationData.setObjectType("user");
locationData.setLongitude(116.3974 + Math.random() * 0.01); // 北京经度范围
locationData.setLatitude(39.9093 + Math.random() * 0.01); // 北京纬度范围
locationData.setAltitude(50.0 + Math.random() * 100);
locationData.setAccuracy(5.0 + Math.random() * 10);
locationData.setSpeed(Math.random() * 80);
locationData.setDirection(Math.random() * 360);
locationData.setTimestamp(System.currentTimeMillis());

// 添加扩展属性
locationData.addExtendedProperty("device_type", "mobile");
locationData.addExtendedProperty("network_type", "4G");

return locationData;
}

/**
* 生成测试位置数据列表
* @param objectId 对象ID
* @param count 数量
* @return 测试位置数据列表
*/
private List<LocationData> generateTestLocationDataList(String objectId, int count) {
List<LocationData> locationDataList = new ArrayList<>();
for (int i = 0; i < count; i++) {
LocationData locationData = generateTestLocationData(objectId + "_" + i);
locationDataList.add(locationData);
}
return locationDataList;
}
}

7. 总结

7.1 Redis实时位置查询最佳实践

  1. 合理设计数据结构: 利用Redis GEO命令设计高效的位置数据结构
  2. 优化内存使用: 合理设置过期时间和数据压缩
  3. 创建地理索引: 利用Redis自动创建的地理索引
  4. 监控位置查询: 实时监控位置查询和存储性能
  5. 异常处理: 实现完善的异常处理和用户友好提示

7.2 性能优化建议

  • 内存优化: 合理配置Redis内存使用
  • 索引优化: 利用Redis GEO索引提升查询性能
  • 缓存策略: 实现位置数据缓存策略
  • 压缩优化: 使用数据压缩减少内存占用
  • 批量操作: 使用批量操作提升性能

7.3 运维管理要点

  • 实时监控: 监控位置查询和存储性能
  • 动态调整: 根据负载情况动态调整Redis配置
  • 异常处理: 建立异常处理和告警机制
  • 日志管理: 完善日志记录和分析
  • 性能调优: 根据监控数据优化Redis性能

通过本文的Redis提供实时位置查询(内存级读写性能)Java实战指南,您可以掌握Redis实时位置查询的原理、实现方法、性能优化技巧以及在企业级应用中的最佳实践,构建高效、实时的位置查询系统!