.NET 大牛们,这次遇到了一个涉及知识盲区的 BUG,与 Redis 有关 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
maymay5
V2EX    .NET

.NET 大牛们,这次遇到了一个涉及知识盲区的 BUG,与 Redis 有关

  •  
  •   maymay5 2024-09-11 19:14:49 +08:00 3151 次点击
    这是一个创建于 462 天前的主题,其中的信息可能已经有所发展或是发生改变。
    • 问题场景:我的 webapi 与 Redis 读写操作有关的 API 全部会 500

    • 检查:Redis 服务一切正常

    • 修复方法:清空所有缓存

    • 无法理解的特殊现象:有两个 webapi ,一个用的 db5 ,一个用的 db1 ,我猜测是 db5 出了问题,但是 db1 的 api 也一起挂掉了,然后我清空了 db5 ,所有服务全部正常了

    • 下面是小弟 debug 到的一段异常,我问了 GPT ,说这是和 缓存副本 相关的异常,可是我的系统并没有做负载均衡类的部署,所以请教各位大佬,这到底是怎么造成的?

    fail: Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware[1] An unhandled exception has occurred while executing the request. StackExchange.Redis.RedisCommandException: Command cannot be issued to a replica: DEL cache_4f4bc6e0-4278-d758-4312-3be96b11d34e at StackExchange.Redis.ConnectionMultiplexer.PrepareToPushMessageToBridge[T](Message message, ResultProcessor`1 processor, IResultBox`1 resultBox, ServerEndPoint& server) in /_/src/StackExchange.Redis/ConnectionMultiplexer.cs:line 1967 at StackExchange.Redis.ConnectionMultiplexer.TryPushMessageToBridgeAsync[T](Message message, ResultProcessor`1 processor, IResultBox`1 resultBox, ServerEndPoint& server) in /_/src/StackExchange.Redis/ConnectionMultiplexer.cs:line 2013 at StackExchange.Redis.ConnectionMultiplexer.ExecuteAsyncImpl[T](Message message, ResultProcessor`1 processor, Object state, ServerEndPoint server) in /_/src/StackExchange.Redis/ConnectionMultiplexer.cs:line 2191 at StackExchange.Redis.RedisBase.ExecuteAsync[T](Message message, ResultProcessor`1 processor, ServerEndPoint server) in /_/src/StackExchange.Redis/RedisBase.cs:line 54 at StackExchange.Redis.RedisDatabase.KeyDeleteAsync(RedisKey key, CommandFlags flags) in /_/src/StackExchange.Redis/RedisDatabase.cs:line 758 at aibotPro.Service.RedisService.DeleteAsync(String key) in /Users/mayday/Desktop/GitHub/AIBot-Pro/AIBot-Pro/aibotPro/aibotPro/Service/RedisService.cs:line 75 at aibotPro.Service.UsersService.GenerateCodeImage(String account, String key) in /Users/mayday/Desktop/GitHub/AIBot-Pro/AIBot-Pro/aibotPro/aibotPro/Service/UsersService.cs:line 151 at aibotPro.Controllers.UsersController.GenerateCodeImage(String key) in /Users/mayday/Desktop/GitHub/AIBot-Pro/AIBot-Pro/aibotPro/aibotPro/Controllers/UsersController.cs:line 388 at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.TaskOfIActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync() --- End of stack trace from previous location --- at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|25_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync() --- End of stack trace from previous location --- at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope) at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger) at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context) at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.<Invoke>g__Awaited|6_0(ExceptionHandlerMiddleware middleware, HttpContext context, Task task) fail: Microsoft.AspNetCore.Mvc.ViewFeatures.ViewResultExecutor[3] The view 'Error' was not found. Searched locations: /Views/Home/Error.cshtml, /Views/Shared/Error.cshtml fail: Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware[3] An exception was thrown attempting to execute the error handler. System.InvalidOperationException: The view 'Error' was not found. The following locations were searched: /Views/Home/Error.cshtml /Views/Shared/Error.cshtml at Microsoft.AspNetCore.Mvc.ViewEngines.ViewEngineResult.EnsureSuccessful(IEnumerable`1 originalLocations) at Microsoft.AspNetCore.Mvc.ViewFeatures.ViewResultExecutor.ExecuteAsync(ActionContext context, ViewResult result) at Microsoft.AspNetCore.Mvc.ViewResult.ExecuteResultAsync(ActionContext context) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResultFilterAsync>g__Awaited|30_0[TFilter,TFilterAsync](ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResultExecutedContextSealed context) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext[TFilter,TFilterAsync](State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultFilters() --- End of stack trace from previous location --- at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|25_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync() --- End of stack trace from previous location --- at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope) at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger) at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context) at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.HandleException(HttpContext context, ExceptionDispatchInfo edi) 
    5 条回复    2024-09-12 10:37:54 +08:00
    v1
        1
    v1  
       2024-09-11 19:25:40 +08:00
    根据报错 < StackExchange.Redis.RedisCommandException: Command cannot be issued to a replica: DEL cache_4f4bc6e0-4278-d758-4312-3be96b11d34e > 来看
    你如果是定义一个实例的时候同时连接 db1 和 db5 的话,组件会默认把 db5 当作 [只读缓存] 副本,通常副本是不允许写入操作的,于是报错了。
    ----

    1. 你应该定义两个 redis 实例并以单例形式添加到服务中:
    ```
    public static IServiceCollection AddStackExchangeRedis(this IServiceCollection services, IConfiguration configuration)
    {
    ConfigurationOptions options1 = new ConfigurationOptions()
    {
    EndPoints = {
    {Address1, Port1 }
    },
    Password = Password1,
    ClientName = Name1,
    DefaultDatabase = DefaultDatabaseNumber1,
    AllowAdmin = true
    };

    ConfigurationOptions options2 = new ConfigurationOptions()
    {
    EndPoints = {
    { Address2, Port2 }
    },
    Password = Password2,
    ClientName = Name2,
    DefaultDatabase = DefaultDatabaseNumber2,
    AllowAdmin = true
    };
    services.AddSingleton<IConnectionMultiplexer>(ConnectionMultiplexer.Connect(options1));
    services.AddSingleton<IConnectionMultiplexer>(ConnectionMultiplexer.Connect(options2));
    return services;
    }
    ```

    2. 使用 IEnumerable 选择对 ClientName ( Name1 或 Name2 )进行查询的任何 redis 实例:
    ```
    public class YourClass
    {
    private readonly IConnectionMultiplexer _connectionMultiplexer;

    public YourClass(IEnumerable<IConnectionMultiplexer> connectionMultiplexer)
    {
    _cOnnectionMultiplexer= connectionMultiplexer.Where(c => c.ClientName == Name1).First();
    }
    }
    ```
    maymay5
        2
    maymay5  
    OP
       2024-09-11 19:31:14 +08:00
    @kk2syc 大佬,场景好像不同,我并不是一个实例连接两个 db ,db1 和 db5 ,完全不是同一个项目,他们是分开部署的两个网站,进程都不是同一个,很奇怪
    v1
        3
    v1  
       2024-09-11 23:30:12 +08:00
    @maymay5 那把两个 webapi 相关 redis 操作时候的各个数据都打 log ,看看会不会有参数为空、类型错误等等,造成死循环挤满 redis 连接了?主要是不理解你描述的。假如你的两个 webapi 不共用 db1 和 db5 的数据,那么 db1 、5 是数据独立的,不存在 db5 的业务挂了影响 db1 的业务。清除 db5 就恢复肯定指向 redis 因为什么卡了
    wuhuiwenzi
        4
    wuhuiwenzi  
       2024-09-12 09:00:43 +08:00
    furion 做的??我遇到过,要定义两个 redis 实例。。类似这种
    _redisCOnnZK= new FullRedis();
    _redisCOnnDS= new FullRedis();
    _redisConnZK.Init(cacheOptions.RedisConnectionStringZK);
    _redisConnDS.Init(cacheOptions.RedisConnectionStringDS);
    maymay5
        5
    maymay5  
    OP
       2024-09-12 10:37:54 +08:00
    @wuhuiwenzi 谢谢解答,我现在怀疑是 StackExchange.Redis 库的一个 bug ,因为我两个 db 完全不在同一个进程中,但事实就是我一个进程中的 db5 挂了(也不能说挂了,因为我用客户端工具依旧可以增删改查,就是程序里用不了),另一个使用 db1 的进程也挂了
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5179 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 35ms UTC 08:17 PVG 16:17 LAX 00:17 JFK 03:17
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86