本文目录导读:

我来为您提供一个完整的PHP指标异常检测方案,包含多种检测算法和实现示例。
基础异常检测类
<?php
class AnomalyDetector
{
private array $data;
private float $threshold;
public function __construct(array $data, float $threshold = 3.0)
{
$this->data = $data;
$this->threshold = $threshold;
}
/**
* 基于标准差的异常检测(Z-Score)
*/
public function zScoreDetection(): array
{
$mean = $this->calculateMean();
$stdDev = $this->calculateStdDev($mean);
if ($stdDev == 0) {
return [];
}
$anomalies = [];
foreach ($this->data as $index => $value) {
$zScore = abs(($value - $mean) / $stdDev);
if ($zScore > $this->threshold) {
$anomalies[$index] = [
'value' => $value,
'z_score' => $zScore,
'mean' => $mean,
'std_dev' => $stdDev
];
}
}
return $anomalies;
}
/**
* 基于IQR(四分位距)的异常检测
*/
public function iqrDetection(): array
{
$sortedData = $this->data;
sort($sortedData);
$q1 = $this->calculatePercentile($sortedData, 25);
$q3 = $this->calculatePercentile($sortedData, 75);
$iqr = $q3 - $q1;
$lowerBound = $q1 - 1.5 * $iqr;
$upperBound = $q3 + 1.5 * $iqr;
$anomalies = [];
foreach ($this->data as $index => $value) {
if ($value < $lowerBound || $value > $upperBound) {
$anomalies[$index] = [
'value' => $value,
'bounds' => [
'lower' => $lowerBound,
'upper' => $upperBound
]
];
}
}
return $anomalies;
}
/**
* 基于移动平均线的异常检测
*/
public function movingAverageDetection(int $windowSize = 5): array
{
$anomalies = [];
$count = count($this->data);
for ($i = $windowSize; $i < $count; $i++) {
$window = array_slice($this->data, $i - $windowSize, $windowSize);
$mean = array_sum($window) / $windowSize;
$stdDev = $this->calculateStdDev($mean, $window);
$currentValue = $this->data[$i];
$deviation = abs($currentValue - $mean);
if ($stdDev > 0 && ($deviation / $stdDev) > $this->threshold) {
$anomalies[$i] = [
'value' => $currentValue,
'mean' => $mean,
'std_dev' => $stdDev,
'deviation' => $deviation
];
}
}
return $anomalies;
}
/**
* 季节性和趋势检测(STL分解)
*/
public function seasonalDetection(int $seasonLength = 24): array
{
$seasonal = [];
$trend = [];
$residual = [];
$count = count($this->data);
// 计算季节性成分
for ($i = 0; $i < $seasonLength; $i++) {
$seasonValues = [];
for ($j = $i; $j < $count; $j += $seasonLength) {
$seasonValues[] = $this->data[$j];
}
$seasonal[$i] = array_sum($seasonValues) / count($seasonValues);
}
// 计算趋势和残差
for ($i = 0; $i < $count; $i++) {
$seasonalComponent = $seasonal[$i % $seasonLength];
// 简单趋势检测
if ($i > 0) {
$trend[$i] = $this->data[$i] - $this->data[$i-1];
} else {
$trend[$i] = 0;
}
$residual[$i] = $this->data[$i] - $seasonalComponent - $trend[$i];
}
// 检测残差的异常
$residualMean = array_sum($residual) / $count;
$residualStdDev = $this->calculateStdDev($residualMean, $residual);
$anomalies = [];
foreach ($residual as $index => $value) {
if ($residualStdDev > 0 && abs($value - $residualMean) > $this->threshold * $residualStdDev) {
$anomalies[$index] = [
'value' => $this->data[$index],
'residual' => $value,
'seasonal' => $seasonal[$index % $seasonLength],
'trend' => $trend[$index]
];
}
}
return $anomalies;
}
/**
* 基于机器学习的检测(简单阈值)
*/
public function mlBasedDetection(): array
{
// 使用K-means聚类简化版
$clusters = $this->simpleKMeans(2);
$anomalies = [];
foreach ($clusters as $clusterId => $clusterData) {
$clusterMean = array_sum($clusterData) / count($clusterData);
$clusterStdDev = $this->calculateStdDev($clusterMean, $clusterData);
foreach ($clusterData as $index => $value) {
$zScore = abs($value - $clusterMean) / ($clusterStdDev ?: 1);
if ($zScore > $this->threshold) {
$anomalies[$index] = [
'value' => $value,
'cluster' => $clusterId,
'z_score' => $zScore
];
}
}
}
return $anomalies;
}
/**
* 综合检测(多种算法结合)
*/
public function compositeDetection(): array
{
$zScoreAnomalies = $this->zScoreDetection();
$iqrAnomalies = $this->iqrDetection();
$movingAnomalies = $this->movingAverageDetection();
// 计算综合评分
$composite = [];
foreach ($this->data as $index => $value) {
$score = 0;
$methods = [];
if (isset($zScoreAnomalies[$index])) {
$score += 2;
$methods[] = 'Z-Score';
}
if (isset($iqrAnomalies[$index])) {
$score += 1;
$methods[] = 'IQR';
}
if (isset($movingAnomalies[$index])) {
$score += 2;
$methods[] = 'Moving Average';
}
if ($score >= 3) { // 至少需要两种方法确认
$composite[$index] = [
'value' => $value,
'score' => $score,
'methods' => $methods,
'timestamp' => time()
];
}
}
return $composite;
}
/**
* 实时监控类
*/
public function realTimeDetection($newValue, $windowSize = 100): bool
{
// 滑动窗口更新
array_push($this->data, $newValue);
if (count($this->data) > $windowSize) {
array_shift($this->data);
}
$zScoreAnomalies = $this->zScoreDetection();
$lastIndex = count($this->data) - 1;
return isset($zScoreAnomalies[$lastIndex]);
}
// 辅助方法
private function calculateMean(): float
{
return array_sum($this->data) / count($this->data);
}
private function calculateStdDev($mean, $data = null): float
{
$data = $data ?: $this->data;
$variance = 0;
$count = count($data);
foreach ($data as $value) {
$variance += pow($value - $mean, 2);
}
return sqrt($variance / ($count - 1));
}
private function calculatePercentile(array $sortedData, float $percentile): float
{
$index = ($percentile / 100) * (count($sortedData) - 1);
$floor = floor($index);
$ceil = ceil($index);
if ($floor == $ceil) {
return $sortedData[$index];
}
$valueAtFloor = $sortedData[$floor];
$valueAtCeil = $sortedData[$ceil];
return $valueAtFloor + ($index - $floor) * ($valueAtCeil - $valueAtFloor);
}
private function simpleKMeans(int $k): array
{
// 简化版K-means实现
$centroids = array_slice($this->data, 0, $k);
$clusters = [];
for ($iterations = 0; $iterations < 10; $iterations++) {
$clusters = array_fill(0, $k, []);
foreach ($this->data as $index => $value) {
$nearestCentroid = 0;
$minDistance = PHP_FLOAT_MAX;
foreach ($centroids as $clusterId => $centroid) {
$distance = abs($value - $centroid);
if ($distance < $minDistance) {
$minDistance = $distance;
$nearestCentroid = $clusterId;
}
}
$clusters[$nearestCentroid][$index] = $value;
}
// 更新质心
foreach ($clusters as $clusterId => $clusterData) {
if (!empty($clusterData)) {
$centroids[$clusterId] = array_sum($clusterData) / count($clusterData);
}
}
}
return $clusters;
}
}
实时监控系统实现
<?php
class MetricsMonitor
{
private PDO $db;
private Redis $redis;
private array $config;
public function __construct(PDO $db, Redis $redis, array $config = [])
{
$this->db = $db;
$this->redis = $redis;
$this->config = array_merge([
'retention_days' => 30,
'alert_threshold' => 3.0,
'check_interval' => 60,
'enabled_methods' => ['zscore', 'iqr', 'moving']
], $config);
}
/**
* 实时监控入口
*/
public function monitor(string $metricKey, $value): void
{
// 记录指标
$this->recordMetric($metricKey, $value);
// 获取历史数据
$historicalData = $this->getHistoricalData($metricKey, 1000);
if (count($historicalData) < 30) {
return; // 数据量不足
}
// 执行异常检测
$detector = new AnomalyDetector($historicalData, $this->config['alert_threshold']);
$anomalies = $detector->compositeDetection();
if (!empty($anomalies)) {
$this->triggerAlert($metricKey, $value, $anomalies);
}
// 缓存最新状态
$this->cacheStatus($metricKey, $value);
}
/**
* 记录指标到数据库
*/
private function recordMetric(string $metricKey, $value): void
{
$stmt = $this->db->prepare(
"INSERT INTO metrics (metric_key, value, created_at) VALUES (?, ?, NOW())"
);
$stmt->execute([$metricKey, $value]);
// 清理过期数据
$this->cleanupOldData();
}
/**
* 获取历史数据
*/
private function getHistoricalData(string $metricKey, int $limit = 1000): array
{
$cacheKey = "metrics:{$metricKey}";
$cached = $this->redis->get($cacheKey);
if ($cached) {
return json_decode($cached, true);
}
$stmt = $this->db->prepare(
"SELECT value FROM metrics WHERE metric_key = ? ORDER BY created_at DESC LIMIT ?"
);
$stmt->execute([$metricKey, $limit]);
$data = $stmt->fetchAll(PDO::FETCH_COLUMN);
$data = array_reverse($data);
// 缓存5分钟
$this->redis->setex($cacheKey, 300, json_encode($data));
return $data;
}
/**
* 触发告警
*/
private function triggerAlert(string $metricKey, $value, array $anomalies): void
{
$alertData = [
'metric' => $metricKey,
'value' => $value,
'anomalies' => $anomalies,
'timestamp' => time()
];
// 发送到告警队列
$this->redis->lpush('alerts:queue', json_encode($alertData));
// 记录日志
error_log("[METRIC ALERT] {$metricKey}: " . json_encode($anomalies));
}
/**
* 缓存指标状态
*/
private function cacheStatus(string $metricKey, $value): void
{
$statusKey = "status:{$metricKey}";
$status = [
'last_value' => $value,
'updated_at' => time(),
'count' => $this->redis->incr("count:{$metricKey}")
];
$this->redis->setex($statusKey, 300, json_encode($status));
}
/**
* 清理过期数据
*/
private function cleanupOldData(): void
{
$retentionDate = date('Y-m-d H:i:s', strtotime("-{$this->config['retention_days']} days"));
$stmt = $this->db->prepare("DELETE FROM metrics WHERE created_at < ?");
$stmt->execute([$retentionDate]);
}
/**
* 批量监控
*/
public function batchMonitor(array $metrics): array
{
$results = [];
foreach ($metrics as $key => $value) {
$this->monitor($key, $value);
$results[$key] = [
'detected' => $this->checkAnomaly($key, $value),
'timestamp' => time()
];
}
return $results;
}
/**
* 检查单个指标是否异常
*/
private function checkAnomaly(string $metricKey, $value): bool
{
$historicalData = $this->getHistoricalData($metricKey, 100);
$detector = new AnomalyDetector($historicalData);
return $detector->realTimeDetection($value);
}
}
自适应阈值检测
<?php
class AdaptiveAnomalyDetector extends AnomalyDetector
{
private array $weights;
private float $learningRate;
public function __construct(array $data, float $threshold = 3.0)
{
parent::__construct($data, $threshold);
$this->learningRate = 0.1;
$this->weights = array_fill(0, count($data), 1.0);
}
/**
* 自适应EWMA(指数加权移动平均)检测
*/
public function ewmaDetection(float $alpha = 0.3): array
{
$ewma = [];
$ewmaVariance = [];
$anomalies = [];
if (empty($this->data)) {
return [];
}
$ewma[0] = $this->data[0];
$ewmaVariance[0] = pow($this->data[0] - $ewma[0], 2);
for ($i = 1; $i < count($this->data); $i++) {
// 更新EWMA
$ewma[$i] = $alpha * $this->data[$i] + (1 - $alpha) * $ewma[$i-1];
// 更新方差
$ewmaVariance[$i] = $alpha * pow($this->data[$i] - $ewma[$i], 2) +
(1 - $alpha) * $ewmaVariance[$i-1];
$stdDev = sqrt($ewmaVariance[$i]);
// 自适应阈值
$adaptiveThreshold = $this->threshold;
if ($stdDev < 0.1 * ($ewma[$i] + 1)) {
$adaptiveThreshold += 0.5; // 波动小时提高阈值
} elseif ($stdDev > $ewma[$i] * 0.5) {
$adaptiveThreshold -= 0.5; // 波动大时降低阈值
}
if ($stdDev > 0 && abs($this->data[$i] - $ewma[$i]) > $adaptiveThreshold * $stdDev) {
$anomalies[$i] = [
'value' => $this->data[$i],
'ewma' => $ewma[$i],
'std_dev' => $stdDev,
'adaptive_threshold' => $adaptiveThreshold,
'anomaly_score' => abs($this->data[$i] - $ewma[$i]) / ($stdDev + 0.001)
];
}
}
return $anomalies;
}
/**
* 基于梯度提升的检测
*/
public function gradientDetection(): array
{
$gradients = [];
$anomalies = [];
// 计算梯度(变化率)
for ($i = 1; $i < count($this->data); $i++) {
$change = $this->data[$i] - $this->data[$i-1];
$percentageChange = ($this->data[$i-1] != 0) ?
($change / $this->data[$i-1]) : 0;
$gradients[$i] = $percentageChange;
}
// 检测梯度异常
$gradientMean = array_sum($gradients) / count($gradients);
$gradientStdDev = $this->calculateStdDev($gradientMean, $gradients);
foreach ($gradients as $index => $gradient) {
$zScore = abs($gradient - $gradientMean) / ($gradientStdDev + 1e-10);
if ($zScore > $this->threshold) {
$anomalies[$index] = [
'value' => $this->data[$index],
'gradient' => $gradient,
'z_score' => $zScore,
'type' => $gradient > 0 ? 'spike' : 'drop'
];
}
}
return $anomalies;
}
/**
* 学习率自适应调整
*/
public function adaptiveLearning(float $error): void
{
$this->learningRate *= (1 + $error);
$this->learningRate = min(0.5, max(0.01, $this->learningRate));
}
}
配置和管理
<?php
class AnomalyDetectionConfig
{
private array $config;
public function __construct(array $config = [])
{
$this->config = array_merge([
'default_threshold' => 3.0,
'detection_methods' => ['zscore', 'iqr', 'moving', 'ewma'],
'data_retention' => 90,
'alert_frequency' => 300,
'max_alerts_per_hour' => 10,
'min_data_points' => 30,
'rolling_window' => 1000,
'enable_ml' => true,
'ml_model_path' => '/models/anomaly_detection.pkl'
], $config);
}
public function get(string $key, $default = null)
{
return $this->config[$key] ?? $default;
}
public function set(string $key, $value): void
{
$this->config[$key] = $value;
}
public function validate(): array
{
$errors = [];
if ($this->config['default_threshold'] <= 0) {
$errors[] = "Threshold must be positive";
}
if ($this->config['data_retention'] < 30) {
$errors[] = "Data retention period too short";
}
if ($this->config['min_data_points'] < 10) {
$errors[] = "Minimum data points too low for reliable detection";
}
return $errors;
}
}
使用示例
<?php
// 基础使用
$data = [10, 12, 11, 13, 12, 11, 14, 15, 12, 100, 13, 12, 11, 14];
$detector = new AnomalyDetector($data, 2.5);
$anomalies = $detector->compositeDetection();
echo "基础异常检测结果:\n";
print_r($anomalies);
// 实时监控
$pdo = new PDO('mysql:host=localhost;dbname=monitoring', 'user', 'pass');
$redis = new Redis();
$redis->connect('localhost', 6379);
$monitor = new MetricsMonitor($pdo, $redis, [
'threshold' => 3.0,
'check_interval' => 60
]);
$monitor->monitor('cpu_usage', 95.5);
// 自适应检测
$adaptiveDetector = new AdaptiveAnomalyDetector($data, 3.0);
$ewmaAnomalies = $adaptiveDetector->ewmaDetection();
$gradientAnomalies = $adaptiveDetector->gradientDetection();
echo "EWMA检测结果:\n";
print_r($ewmaAnomalies);
echo "梯度检测结果:\n";
print_r($gradientAnomalies);
数据库表结构
-- 指标表
CREATE TABLE metrics (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
metric_key VARCHAR(255) NOT NULL,
value DECIMAL(12,4) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_metric_key (metric_key),
INDEX idx_created_at (created_at)
) ENGINE=InnoDB;
-- 告警表
CREATE TABLE alerts (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
metric_key VARCHAR(255) NOT NULL,
severity ENUM('info', 'warning', 'critical') DEFAULT 'warning',
description TEXT,
data JSON,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
status ENUM('open', 'acknowledged', 'resolved') DEFAULT 'open',
INDEX idx_metric_key (metric_key),
INDEX idx_status (status)
) ENGINE=InnoDB;
-- 检测配置表
CREATE TABLE detection_configs (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
metric_key VARCHAR(255) NOT NULL UNIQUE,
threshold DECIMAL(5,2) DEFAULT 3.00,
methods JSON,
window_size INT DEFAULT 1000,
update_frequency INT DEFAULT 300,
CONSTRAINT chk_threshold CHECK (threshold > 0)
) ENGINE=InnoDB;
这个方案提供了:
- 多种检测算法:Z-Score、IQR、移动平均、EWMA、梯度检测等
- 实时监控能力:实时检测和历史数据分析
- 自适应学习:根据数据特征动态调整阈值
- 完整的告警机制:告警记录、状态管理和通知
- 灵活配置:可按指标定制检测策略
您可以根据具体需求选择合适的检测方法或组合使用。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播