lettuce 监控日志

43 篇文章 2 订阅
15 篇文章 0 订阅

代码地址:

https://github.com/singgel/lettuce-infra/

问题:

线上的redis日志不是很全面,例如:

1.无法得知数据返回的remote address

2.没有主动记录slowlog慢查询日志

3.没有记录connection连接状态

4.没有集群的网络拓扑

分析:

按照官方提供的EventBus总线,异步事件流提供了metric指标信息

https://github.com/lettuce-io/lettuce-core/wiki/Connection-Events

根据官方的Collector事件采集,提供了address之类相关信息

https://github.com/lettuce-io/lettuce-core/wiki/Command-Latency-Metrics

解决:

根据以上相关帮助文档,采用适配器模式方便Event扩展,采用工厂模式将EventBus添加进消费序列

压测:

原生lettuce基准测试OPS与lettuce封装后基准测试 ops表现一致

测试代码:

原生lettuce JMH基准测试代码

package com.lettuce.metric;

/**
 * @author heks
 * @description: TODO
 * @date 2020/3/27
 */

import com.codahale.metrics.MetricRegistry;
import com.google.common.collect.ImmutableList;
import com.lettuce.metric.visitor.*;
import io.lettuce.core.RedisClient;
import io.lettuce.core.RedisFuture;
import io.lettuce.core.RedisURI;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.api.sync.RedisCommands;
import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;

import java.time.Duration;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

@BenchmarkMode(Mode.Throughput)
@Warmup(iterations = 1)
@Threads(200)
@State(Scope.Benchmark)
@Measurement(iterations = 2, time = 600, timeUnit = TimeUnit.MILLISECONDS)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
public class LettuceBenchmarkTest {
    private static final int LOOP = 1;
    private static final String clusterName = "localhost";
    private StatefulRedisConnection<String, String> connection;
    private MetricRegistry metrics;
    @Setup
    public void setup() {
        metrics = new MetricRegistry();
        RedisURI redisUri = RedisURI.builder()
                .withHost("localhost")
                .withPort(6379)
                .withTimeout(Duration.of(10, ChronoUnit.SECONDS))
                .build();
        RedisClient client = RedisClient.create(redisUri);
        client.getResources()
                .eventBus()
                .get()
                .subscribe(new LettuceMetricsSubscriber(buildEventVisitors(metrics)));
        connection = client.connect();
        connection.sync().ping();
    }

    protected List<EventVisitor> buildEventVisitors(final MetricRegistry metrics) {
        // Extract this, and the event wrapper builders, to Dropwizard factories, if more event types are added frequently enough?
        return ImmutableList.of(
                new ClusterTopologyChangedEventVisitor(clusterName, metrics),
                new CommandLatencyEventVisitor(clusterName, metrics),
                new ConnectedEventVisitor(clusterName, metrics),
                new ConnectionActivatedEventVisitor(clusterName, metrics),
                new ConnectionDeactivatedEventVisitor(clusterName, metrics),
                new DisconnectedEventVisitor(clusterName, metrics)
        );
    }

    @Benchmark
    public void get() throws ExecutionException, InterruptedException {
        RedisCommands<String, String> commands = connection.sync();
        List<RedisFuture<String>> redisFutureList = new ArrayList<>();
        for (int i = 0; i < LOOP; ++i) {
            commands.get("a");
            /*RedisFuture<String> future = commands.get("a");
            redisFutureList.add(future);
            future.get();*/
        }
        /*redisFutureList.forEach(f -> {
            try {
                f.get();
            } catch (Exception e) {
                e.printStackTrace();
            }
        });*/
    }

    public static void main(String[] args) throws RunnerException {
        Options options = new OptionsBuilder()
                .include(LettuceBenchmarkTest.class.getSimpleName())
                .forks(1)
                .build();
        new Runner(options).run();
    }
}

备注:

不涉及lettuce核心源码和RedisCluster4核心逻辑,故没有snapshot版本预发布

slowlog慢日志记录了10ms以上的

if (firstResponseLatency > 10000000 || completionLatency > 10000000) {
    log.warn("REDIS4 slowlog | " + local.toString() + " -> " + remote.toString() + " | " + commandType.name() + " | firstResponseLatency:" + firstResponseLatency + " ns | completionLatency:" + completionLatency + " ns");
}

 

metric打点记录了commandType和remoteAddr

String tagFormate = commandType.name() + "." + remote.toString().substring(1).replace(".", "-");
metrics.timer(tagFormate).update(firstResponseLatency, TimeUnit.NANOSECONDS);
metrics.timer(tagFormate).update(completionLatency - firstResponseLatency, TimeUnit.NANOSECONDS);

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值