StackExchange.Redis加锁机制实例

2023-10-26

1、redis下载安装 

Github下载地址:https://github.com/MicrosoftArchive/redis/releases

安装过程不做写明

1、VS引用StackExchange.Redis

通过“工具”=》“库程序包管理器”=》“程序包管理器控制台”

pm>Install-Package StackExchange.Redis -Version 1.2.5

也可通过vs中NuGet获取--(不建议此方式,因为你所用的.net freamwork版本不一定一直,可用过https://www.nuget.org/packages/StackExchange.Redis这个redis官网查看所用freamwork版本对应的redis版本,用控制台添加引用)

using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication5
{
    class Program
    {
        static ConnectionMultiplexer redis;
        static IDatabase _db;
        static RedisValue Token = Environment.MachineName;
        static void Main(string[] args)
        {
            var options = ConfigurationOptions.Parse("localhost");
            options.AllowAdmin = true;
            redis = ConnectionMultiplexer.Connect(options);
            _db = redis.GetDatabase();

            //未使用锁  2个线程同时对一个数据进行加操作
            for (var i = 0; i < 2; i++)
            {
                var key = "key";
                Task.Factory.StartNew((index) =>
                {
                    for (var j = 0; j < 100; j++)
                    {
                        var tmp = _db.StringGet(key);
                        var data = 0;
                        int.TryParse(tmp, out data);
                        _db.StringSet(key, (data + 1).ToString(), TimeSpan.FromSeconds(5));
                    }
                    Console.WriteLine("[未锁]-线程" + (Convert.ToInt32(index) + 1) + "值为:" + _db.StringGet(key));
                }, i);
            }

            //使用第三方锁
            for (var i = 0; i < 2; i++)
            {
                Task.Factory.StartNew((index) =>
                {
                    var key = "key2";
                    for (var j = 0; j < 100; j++)
                    {
                        while (true)
                        {
                            if (StringLockToUpdate(key))
                                break;
                        }
                    }
                    Console.WriteLine("[StackExchange锁]-线程" + (Convert.ToInt32(index) + 1) + "值为:" + _db.StringGet(key));
                }, i);
            }

            //使用自己写的代码级锁
            for (var i = 0; i < 2; i++)
            {
                var key = "key3";
                Task.Factory.StartNew((index) =>
                {
                    for (var k = 0; k < 100; k++)
                    {
                        StringLockToUpdateByNormalLock(key);
                    }
                    Console.WriteLine("[代码级锁]-线程" + (Convert.ToInt32(index) + 1) + "值为:" + _db.StringGet(key));
                }, i);
            }
            Console.WriteLine("完成");
            Console.ReadKey();
        }

        /// <summary>
        /// StackExchange.redis锁
        /// </summary>
        /// <param name="key">数据Key</param>
        /// <returns></returns>
        static bool StringLockToUpdate(string key)
        {
            var flag = false;
            //设置timespan避免死锁,“LockKey”为锁的名字,共同操作时此处唯一
            if (_db.LockTake("LockKey", Token, TimeSpan.FromSeconds(5)))
            {
                try
                {
                    var tmp = _db.StringGet(key);
                    var data = 0;
                    int.TryParse(tmp, out data);
                    _db.StringSet(key, data + 1, TimeSpan.FromSeconds(5));
                    flag = true;
                }
                catch (Exception)
                { 
                    var b = string.Empty;
                }
                finally
                {
                    _db.LockRelease("LockKey", Token);
                }
            }
            return flag;
        }


        static object myLock = new object();
        /// <summary>
        /// 代码级锁实现锁
        /// </summary>
        /// <param name="key">数据key</param>
        static void StringLockToUpdateByNormalLock(string key)
        {
            lock (myLock)
            {
                var tmp = _db.StringGet(key);
                var data = 0;
                int.TryParse(tmp, out data);
                _db.StringSet(key, data + 1, TimeSpan.FromSeconds(5));
            }
        }
    }

}

未使用锁的情况下,两个线程同时对同一个redis值进行变更,最终值无法按照我们预期保证数据准确。
代码级锁和StackExchange锁都实现了我们预期的效果;
根据业务需要,使用StackExchange锁或代码级锁均可实现锁效果。

StackExchange锁和代码级锁都实现了同样的效果
StackExchange是通过不断重试(While)来实现每一次每一次循环的操作都有效执行;
代码级锁中使用了Lock,他的实现是类似队列的;
所以从实现上述业务效果的性能上来看,代码级锁应该优于不断重试的方式; 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

StackExchange.Redis加锁机制实例 的相关文章

  • 如何在 Docker 容器(Python、Flask 和 Redis)中启动自定义 RQ Worker

    我遵循 Miguel Grinberg 的优秀 Flask Mega 教程 成功设置了一个包含 Redis 任务队列和 RQ 工作线程的 Flask Web 应用程序 所有这些都在 Docker 容器中 为了提高任务队列性能 我现在需要使用
  • 如何查看我的 Redis 数据库 current_size?

    我知道 redis cli 以及 info 和 config 命令 但是 他们没有任何说明当前数据库大小的信息 我怎样才能弄清楚这一点 使用INFO命令 完整详细信息在这里 http redis io commands info http
  • 以原子方式从 Redis 数据结构中弹出多个值?

    是否有一个 Redis 数据结构 允许弹出 获取 删除 其中包含的多个元素的原子操作 有众所周知的 SPOP 或 RPOP 但它们总是返回单个值 因此 当我需要 set list 中的前 N 个值时 我需要调用该命令 N 次 这是昂贵的 假
  • Redis CLI 未通过 Laravel 显示最近存储的密钥

    我正在尝试使用缓存我的结果redis in Laravel通过做这个 result Cache remember orders cache 10 function use orders return orders return result
  • RQ - 清空和删除队列

    我在用着RQ http python rq org 我有一个failed排队有数千件物品 还有另一个test我不久前创建的用于测试的队列现在是空的且未使用 我想知道如何删除所有作业failed排队 然后删除test完全排队吗 对于基本问题表
  • 如何隔离Spring Boot应用程序Redis和Spring Boot会话全局Redis

    据我所知 spring boot和spring session为我们提供了一站式自动配置 但是当我的应用程序使用会话redis和应用程序缓存redis时 不是同一个redis服务器 我该如何配置呢 非常感谢您的回复 事实上 默认情况下 sp
  • ruby redis 客户端扫描与密钥

    我正在寻找一些有关 redis 的 ruby 客户端的文档 但没有成功 我正在使用密钥 但我听说它们在生产 redis 中的性能很糟糕 redis Redis new host Settings redis host port Settin
  • Redis - 考虑重命名其中一个 bean 或通过设置 spring.main.allow-bean-definition-overriding=true 来启用覆盖

    我正在开发Spring Boot Spring Data Redis例子 在此示例中 我正在开发以下代码RedisMessageListenerContainer并在这里定义相应的bean 现在 当我运行该应用程序时 出现以下错误 有人可以
  • 为什么我不能让单个 Redis 客户端在同一连接中充当 PUB 和 Sub ?

    我的思维模型是 聊天 我订阅了某个频道 并且可以向该频道发布消息 由于 pub sub 是异步的 因此发布的消息可能随时出现 包括当您期望命令响应时 尽管 Redis 是单线程的 通常会阻止此类事情 但网络延迟可能会导致一些有趣的影响 根据
  • Predis 给出“从服务器读取行时出错”

    我在用predis https github com nrk predis 它已订阅频道并正在收听 它抛出以下错误 如下 并在 60 秒后死亡 这肯定不是我的网络服务器错误或其超时 有一个类似的问题正在讨论here https github
  • 如何在多线程应用程序中使用 StackExchange.Redis IDatabase 对象?

    我从 StackExchange Redis 文档中收到有关如何使用 IDatabase 的混合消息 在里面基本使用文档 https github com StackExchange StackExchange Redis blob mas
  • 在节点中使用redis获取hash key的所有字段和值

    红色是使用哈希 我需要存储具有多个字段和值的哈希键 我尝试如下 client hmset Table1 Id 9324324 ReqNo 23432 redis print client hmset Table1 Id 9324325 Re
  • 使用 sidekiq 处理两个独立的 Redis 实例?

    下午好 我有两个独立但相关的应用程序 他们都应该有自己的后台队列 阅读 单独的 Sidekiq 和 Redis 进程 然而 我希望偶尔能够将工作推给app2的队列来自app1 从简单的队列 推送的角度来看 如果app1没有现有的 Sidek
  • AWS Redis 从外部连接

    有没有办法从外部 AWS 网络连接 AWS 上托管的 Redis 实例 我有一个基于 Windows 的 EC2 实例在 AWS 上运行 另一个是 Redis 缓存节点 我知道有人问过这个问题 但答案是在基于 Linux 的系统中 但我的是
  • Redis 块推送直到列表有空位

    我正在寻找类似的东西BLPUSH该命令将阻塞 直到列表的长度低于指定值max size 目的是防止生产者运行速度快于消费者时列表无限增长 功能与 python 非常相似Queue put https docs python org 3 li
  • 我的 Redis 自动生成的密钥

    我不知道我的 Redis 版本 4 0 9 到底发生了什么 我正在运行一个应用程序并使用 Redis 来存储我的数据库 但是 然后 Redis 自动创建 3 个新键 Backup1 Backup2 Backup3 并删除我的所有数据 这是我
  • redis集群不断打印日志WSA_IO_PENDING

    当我启动redis集群的所有redis服务器时 所有这些服务器不断打印类似WSA IO PENDING clusterWriteDone的日志 9956 03 Feb 18 17 25 044 WSA IO PENDING writing
  • Docker-compose Predis 不通过 PHP 连接

    我正在尝试使用 docker compose 将 PHP 与 redis 连接 docker compose yml version 2 services redis image redis 3 2 2 php image company
  • Redis hash写入速度非常慢

    我面临一个非常奇怪的问题 使用 Redis 时 我的写入速度非常糟糕 在理想的情况下 写入速度应该接近 RAM 上的写入速度 这是我的基准 package redisbenchmark import redis clients jedis
  • 在 aws-elasticache 上使用 memcached 或 Redis

    我正在 AWS 上开发一个应用程序 并使用 AWS elasticache 进行缓存 我对使用 memcached 或 redis 感到困惑 我阅读了有关 redis 3 0 2 更新以及它现在如何等同于 memchached 的文章 ht

随机推荐

  • java中值传递和引用传递

    目录 值传递 引用传递 Java 中有两种数据类型 请谈一下值传递与引用传递 Java 中只有值传递么 值传递 package com github hcsp public class Main public static void mai
  • JAVA单元测试框架-6-Enable priority

    1 enabled属性 在Testng中 如果方法前面添加了 Test注释 然后没有其他的属性 那么默认这个用例会被自动运行 当测试用例没有书写完成 或者不想测试时 可以采用注解 Test enable false 来禁止测试用例的执行 E
  • 如何自学图像编程

    如何自学图像编程 现在 图像类信息越来越多了 对图像的编程需求也越来越多 图像类项目的特点是性价比高 单行代码的价格一般是普通的程序的10倍 每行代码能够卖几块钱 很多人把目光放在这个上面 刚才又有网友咨询 做图像要看些什么书 结合我的自学
  • VSCode打开多个文件时实现标签栏多行显示

    默认情况下 VSCode的标签栏是滚动式的 当打开多个文件时是在同一行中显示的 想要选择查看某个文件时很不方便 如果想要实现多行显示标签页 也是可以的 具体方法如下 操作步骤 1 安装Custom CSS and JS Loader插件 2
  • 相关子查询和不相关子查询

    相关子查询 比如 select t id t name t pass from student t where 80 lt select f score from f where f id t id and f name xxx 这就是1个
  • AICG,人工智能自动生成内容——根据文本生成图像,视频,音频

    文章目录 1 什么是AICG 2 Text2Video 3 Text2Image 4 Text2Audio 5 AICG的发展趋势 1 什么是AICG 什么是AICG AICG是指人工智能自动生成内容 通过算法模型 将文本转化为图像 音频
  • [原]通过GitHub Pages建立个人站点(详细步骤)

    1 Git简介 2 为什么使用Github Pages 3 创建Github Pages 3 1 安装git工具 3 2 两种pages模式 3 3 创建步骤 3 4 常用命令 4 使用Jekyll搭建博客 4 1 什么是jekyll 4
  • 【微信小程序】wx.login 和 wx.getUserProfile 同时使用问题

    场景 在使用微信登录时 通常会在调用 wx login 获取 code 后再通过 wx getUserProfile 获取 iv 和 encryptedData 加密数据 一起发到后端进行登录验证 但是 在实际使用中如果在 wx login
  • HTML+CSS实现按钮居中

    居中的方式有很多 这里以button为例 它是一个行内块级元素display inline block 所以处理方式很简单 可以用以下两种方式 方式一 div style text align center div
  • 1116. 打印零与奇偶数

    现有函数 printNumber 可以用一个整数参数调用 并输出该整数到控制台 例如 调用 printNumber 7 将会输出 7 到控制台 给你类 ZeroEvenOdd 的一个实例 该类中有三个函数 zero even 和 odd Z
  • 数据库SQL优化大总结之 百万级数据库优化方案

    网上关于SQL优化的教程很多 但是比较杂乱 近日有空整理了一下 写出来跟大家分享一下 其中有错误和不足的地方 还请大家纠正补充 这篇文章我花费了大量的时间查找资料 修改 排版 希望大家阅读之后 感觉好的话推荐给更多的人 让更多的人看到 纠正
  • 【Xilinx Vivado时序分析/约束系列3】FPGA开发时序分析/约束-保持时间

    目录 基本概念 数据结束时间 Data finish time 时钟到达时间 Clock arrival time 保持时间门限 保持时间余量 Hold Slack 往期系列博客 基本概念 数据结束时间 Data finish time 之
  • win10+中标麒麟双系统安装步骤

    win7 10 中标麒麟双系统安装步骤 场景要求 联想启天M415台机出厂预装的是win10 现在要改成win7和中标麒麟7 0双系统 开机在选择系统界面要有两个系统选择 并且默认进入win7 注 先安装win7 再安装中标麒麟 一开始是用
  • MySQL--order by升序与降序、count计数与子查询

    MySQL order by升序与降序 count计数与子查询 1 创建表格 2 题目部分 1 升序与降序 order by 2 count 计数 3 子查询 3 文末彩蛋 轻松一刻 更多关于数据库知识请加关注哟 若需联系和想安装MySQL
  • 打印预览的时候,总是会多于一个空白页,怎么办?

    media print printTest 要打印的区域 display block width 100 height auto overflow hidden 在页面内加入此样式即可
  • PyTorch-01初见

    PyTorch 01初见 同类框架 PyTorch生态 PyTorch能做什么 1 GPU加速 import torch import time print torch version print torch cuda is availab
  • 零基础!搭建好本地的ChatGPT!

    当搭建好本地的GPT 你可以充分利用OpenAI的功能 无需使用任何魔法 并且免去了许多烦恼和难题 通过魔法访问gpt遇到过很多问题吗 以下是你搭建的本地GPT的一些关键特点 功能全面 你的本地GPT能够使用OpenAI的全部功能 让你体验
  • 11 前端模块化

    文章目录 为什么有前端模块化 以前的解决办法 了解CommonJS es6的模块化 export 导出 import 导入 为什么有前端模块化 首先 如果多人合作开发一个项目 你的a js用了一个变量a 你同事的b js也用了一个变量a 那
  • mybatis学习文档

    mybatis 9 28 环境 JDK1 8 mysql 8 0 16 maven3 6 1 IDEA 回顾 JDBC mysql jave基础 Maven junit 1 简介 1 1 什么是mybatis mybatis是支持普通SQL
  • StackExchange.Redis加锁机制实例

    1 redis下载安装 Github下载地址 https github com MicrosoftArchive redis releases 安装过程不做写明 1 VS引用StackExchange Redis 通过 工具 库程序包管理器