【问题标题】:Redis : New Keys not persisted in concurrent requestsRedis:新密钥未保留在并发请求中
【发布时间】:2018-01-01 18:16:18
【问题描述】:

我们在我们的应用程序中集成了 Redis 缓存,在正常情况下运行良好。最近我们在我们的应用程序中发现了一个非常奇怪的问题,即在并发 ajax 请求的情况下,新添加的键会被自动删除,而修改的键具有旧值。 场景如下:

Ajax 请求 1: - 从数据库读取数据,大约需要 5-6 秒才能返回 - 在页面加载时触发(document.ready 事件)

Ajax 请求 2: - 触发按钮点击 - 在会话中设置值 - 在 Ajax 请求 1 完成之前完成

Ajax 请求 3: - 只需读取会话值 - 找到旧值,应该已经收到 Ajax 请求 2 设置的值

所以这里的顺序是这样的:

1) Ajax Req 1 触发并开始处理,

2) Ajax Req 2 触发,设置会话中的值(修改现有以及添加新键)

3) Ajax Req 2 完成

4) Ajax Req 1 完成

5) Ajax Req 3 被触发,得到了 Req 1 的旧值,应该已经收到了 Req 2 设置的值

最初我们认为一定有一些代码覆盖了值,但没有找到这样的代码。

我尝试使用示例应用程序重现相同的案例,并且能够在那里看到类似的案例。 以下是源代码:

public JsonResult Test1()
        {
            Session["MyTest"] = "Vijay";
            SessionManager.ProposalRequestID = 1;
            SessionManager.VendorID = 2;

            return Json(new { reqID = SessionManager.ProposalRequestID, venID = SessionManager.VendorID, mytest = Session["MyTest"] }, JsonRequestBehavior.AllowGet);
        }

        public JsonResult Test2()
        {
            System.Threading.Thread.Sleep(3000);
            return Json(new { reqID = SessionManager.ProposalRequestID, venID = SessionManager.VendorID, mytest = Session["MyTest"] }, JsonRequestBehavior.AllowGet);
        }

        public JsonResult Test3()
        {
            return Json(new { reqID = SessionManager.ProposalRequestID, venID = SessionManager.VendorID, mytest = Session["MyTest"] }, JsonRequestBehavior.AllowGet);
        }

用户界面如下:

<body>
    <div>
        <button id="btn1">Set Session</button>
        <button id="btn2">Heavy Task</button>
        <button id="btn3">Use Session</button>
    </div>
    <div style="color:red;height:500px;overflow-y:auto">
        <span id="message"></span>
    </div>
</body>

<script type="text/javascript">

    $(document).ready(function () {
        SendTestAjaxCall('@Url.Action("Test2")', "Heave Task");

        $('#btn1').click(function () { SendTestAjaxCall('@Url.Action("Test1")', "Set Session") });
        $('#btn2').click(function () { SendTestAjaxCall('@Url.Action("Test2")', "Heave Task") });
        $('#btn3').click(function () { SendTestAjaxCall('@Url.Action("Test3")', "User Session") });
    });

    function SendTestAjaxCall(URL, message) {
        addToLog("Sending request for  " + message);
        $.ajax({
            url: URL,
            success: function (result) {
                addToLog("Response from " + message, result);
            }
        });
    }

    function addToLog(message, data) {
        $("#message").html($("#message").html() + '<p>' + message + '</p>');
        if (data) {
            addToLog(JSON.stringify(data), null);
        }
    }

</script>

【问题讨论】:

  • 在 ajax 中添加 async :false 并告诉我结果。
  • async: false 将起作用,因为它将开始同步处理请求,但随后它将开始显示性能问题,这对我来说又是一个新问题。
  • 你有什么解决办法吗?

标签: asp.net-mvc session concurrency redis


【解决方案1】:

最后我找到了解决方案,它与 Redis 无关,但它与我们应用程序中的中间层有关,它管理来自同一用户的请求之间的锁定机制。我们发现这一点是基于 Redis 始终存储在键值对中的事实,它将始终更新存储中的最后一个给定值,但是我们的自定义中间层总是在请求结束时恢复会话,因此最后结束的请求将恢复其会话。 抱歉对 Redis 的无效怀疑

【讨论】:

    猜你喜欢
    • 2014-02-01
    • 2015-09-23
    • 2013-01-25
    • 2021-05-01
    • 2018-01-08
    • 2020-09-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多