GVKun编程网logo

Stackexchange.Redis的开火和遗忘保证交货吗?

26

在这篇文章中,我们将为您详细介绍Stackexchange.Redis的开火和遗忘保证交货吗?的内容。此外,我们还会涉及一些关于.netcore使用redis基于StackExchange.Redis

在这篇文章中,我们将为您详细介绍Stackexchange.Redis的开火和遗忘保证交货吗?的内容。此外,我们还会涉及一些关于.net core使用redis基于StackExchange.Redis、ASP.NET Core 使用 Redis 实现分布式缓存:Docker、IDistributedCache、StackExchangeRedis、C# redis StackExchange、C# StackExchange.Redis 用法总结的知识,以帮助您更全面地了解这个主题。

本文目录一览:

Stackexchange.Redis的开火和遗忘保证交货吗?

Stackexchange.Redis的开火和遗忘保证交货吗?

我了解这CommandFlags.FireAndForget是针对您不关心响应的情况。

即使响应对于正在运行的应用程序并不重要,它也可以保证交付吗?

答案1

小编典典

实际上,Redis协议并不真正支持“即发即弃”操作。除了发布/订阅流量外,所有Redis命令都与答复匹配,并且无法告诉Redis服务器忽略答复。

现在,某些客户端(例如StackExchange.Redis)通过协议的异步实现来模拟“解雇”模式。实际上,StackExchange.Redis中的“即发即弃”模式与“异步”模式非常相似,不同之处在于,在收到答复后,它们只会被丢弃。

它可靠吗?好吧,只要TCP / IP保证交付,它就保证交付。网络将尽力传输数据包(如果其中某些数据包丢失,最终将再次传输数据包),但这全部由TCP处理。

现在,如果服务器关闭或决定关闭连接,则客户端仅在尝试从套接字读取时才知道。StackExchange.Redis可能会愉快地继续在无效连接上发送命令一段时间。如果您有中间层(例如Twemproxy),情况可能会更糟。

换句话说,“即发即弃”流量通常会发送到服务器,并且网络上不会丢失任何消息,但是如果您遇到服务器或连接问题,则在客户端有机会注意到之前可能会丢失一些流量。它。我将此称为尽力而为行为。

.net core使用redis基于StackExchange.Redis

.net core使用redis基于StackExchange.Redis

.net core使用redis基于StackExchange.Redis教程,具体如下

一.添加引用包

StackExchange.Redis
Microsoft.Extensions.Configuration

二.修改配置文件 appsettings.json

{
 "RedisConfig": {
  "Redis_Default": {
   "Connection": "127.0.0.1: 6379","InstanceName": "Redis1: "
  },"Redis_6": {
   "Connection": "127.0.0.1: 6379","DefaultDatabase": 6,"InstanceName": "Redis2: "
  }
 }
}

三.简单封装
RedisClient.cs类

public class RedisClient : Idisposable
{
 private IConfigurationRoot _config;
 private ConcurrentDictionary<string,ConnectionMultiplexer> _connections;
 public RedisClient(IConfigurationRoot config)
 {
  _config = config;
  _connections = new ConcurrentDictionary<string,ConnectionMultiplexer>();
 }
 /// <summary>
 /// 获取ConnectionMultiplexer
 /// </summary>
 /// <param name="redisConfig">RedisConfig配置文件</param>
 /// <returns></returns>
 private ConnectionMultiplexer GetConnect(IConfigurationSection redisConfig)
 {
  var redisinstanceName = redisConfig["InstanceName"];
  var connStr = redisConfig["Connection"];
  return _connections.GetorAdd(redisinstanceName,p => ConnectionMultiplexer.Connect(connStr));
 }
 /// <summary>
 /// 检查入参数
 /// </summary>
 /// <param name="configName">RedisConfig配置文件中的 Redis_Default/Redis_6 名称</param>
 /// <returns></returns>
 private IConfigurationSection CheckeConfig(string configName)
 {
  IConfigurationSection redisConfig = _config.GetSection("RedisConfig").GetSection(configName);
  if (redisConfig == null)
  {
   throw new ArgumentNullException($"{configName}找不到对应的RedisConfig配置!");
  }
  var redisinstanceName = redisConfig["InstanceName"];
  var connStr = redisConfig["Connection"];
  if (string.IsNullOrEmpty(redisinstanceName))
  {
   throw new ArgumentNullException($"{configName}找不到对应的InstanceName");
  }
  if (string.IsNullOrEmpty(connStr))
  {
   throw new ArgumentNullException($"{configName}找不到对应的Connection");
  }
  return redisConfig;
 }
 /// <summary>
 /// 获取数据库
 /// </summary>
 /// <param name="configName"></param>
 /// <param name="db">默认为0:优先代码的db配置,其次config中的配置</param>
 /// <returns></returns>
 public IDatabase GetDatabase(string configName = null,int? db = null)
 {
  int defaultDb = 0;
  IConfigurationSection redisConfig = CheckeConfig(configName);
  if (db.HasValue)
  {
   defaultDb = db.Value;
  }
  else
  {
   var strDefalutDatabase = redisConfig["DefaultDatabase"];
   if (!string.IsNullOrEmpty(strDefalutDatabase) && Int32.TryParse(strDefalutDatabase,out var intDefaultDatabase))
   {
    defaultDb = intDefaultDatabase;
   }
  }
  return GetConnect(redisConfig).GetDatabase(defaultDb);
 }

 public IServer GetServer(string configName = null,int endPointsIndex = 0)
 {
  IConfigurationSection redisConfig = CheckeConfig(configName);
  var connStr = redisConfig["Connection"];

  var confOption = Configurationoptions.Parse((string)connStr);
  return GetConnect(redisConfig).GetServer(confOption.EndPoints[endPointsIndex]);
 }

 public ISubscriber GetSubscriber(string configName = null)
 {
  IConfigurationSection redisConfig = CheckeConfig(configName);
  return GetConnect(redisConfig).GetSubscriber();
 }

 public void dispose()
 {
  if (_connections != null && _connections.Count > 0)
  {
   foreach (var item in _connections.Values)
   {
    item.Close();
   }
  }
 }
}

因为RedisClient 中使用了ConcurrentDictionary
所以,有了RedisClientSingleton.cs类

public class RedisClientSingleton
{
 private static RedisClient _redisClinet;
 private RedisClientSingleton() { }

 private static object _lockObj = new object();
 public static RedisClient GetInstance(IConfigurationRoot config)
 {
  if (_redisClinet == null)
  {
   lock (_lockObj)
   {
    if (_redisClinet == null)
    {
     _redisClinet = new RedisClient(config);
    }
   }
  }
  return _redisClinet;
 }
}

四.测试

1、控制台程序

1)创建一个Controller程序
2)添加引用包
Microsoft.Extensions.Configuration
Microsoft.Extensions.Configuration.Json
3)添加appsettings.json

添加以下

"RedisConfig": {
 "Redis_Default": {
  "Connection": "127.0.0.1:6379","InstanceName": "Redis1:"
 },"Redis_6": {
  "Connection": "127.0.0.1:6379","InstanceName": "Redis2:"
 }
 }

4)修改Program类

①添加引用using Microsoft.Extensions.Configuration;
②修改Main

static void Main(string[] args)
 {
   var builder = new ConfigurationBuilder()
    .SetBasePath(Directory.GetCurrentDirectory())
    .AddJsonFile("appsettings.json");
   IConfigurationRoot configuration = builder.Build();

   var redisClient = RedisClientSingleton.GetInstance(configuration);   

   var redisDatabase = redisClient.GetDatabase("Redis_Default");

   redisDatabase.StringSet("TestStrKey","TestStrValue");
} 

③运行后可以看到

2、web程序

①创建一个core的mvc项目
②修改Startup.cs文件
修改ConfigureServices函数

public void ConfigureServices(IServiceCollection services)
{
 ...
 services.AddSingleton(Configuration);
 ...
}

其中的Configuration是 public IConfigurationRoot Configuration { get; }

③创建一个TestController
在修改构造函数
SimpleRedisExt _redisExt;

public TokenTranslateController(IConfigurationRoot config)//,IConfigurationRoot config)
{
 _config = config;
 IDatabase redisDataBase = RedisClientSingleton.GetInstance(_config).GetDatabase("Redis_Default");
}
 
public string Post(string value)
{
 redisDataBase.StringSet("TestMvcRedis",value);
}

④运行value = TestMvcRedisValue 后得到

随手写的,写得比较糙。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程小技巧。

您可能感兴趣的文章:

  • .net core如何使用Redis发布订阅
  • 详解Asp.net Core 使用Redis存储Session
  • .NET Core中使用Redis与Memcached的序列化问题详析

ASP.NET Core 使用 Redis 实现分布式缓存:Docker、IDistributedCache、StackExchangeRedis

ASP.NET Core 使用 Redis 实现分布式缓存:Docker、IDistributedCache、StackExchangeRedis

ASP.NET Core 使用 Redis 实现分布式缓存:Docker、IdistributedCache、StackExchangeRedis

前提:一台 Linux 服务器、已安装 Docker。

一,Docker 中运行 Redis

拉取 Redis 镜像

docker pull redis

查询镜像列表

docker imgaes

运行 Redis的几种方法

①运行并且设置 Redis 端口

docker run -p 6379:6379 -d redis:latest redis-server

docker run -p 6379:6379 -d {镜像id} redis-server

③持久化

将 Docker 里的 Redis 数据持久化到物理机

docker run -p 6379:6379 -v {物理机路径}:/data  -d redis:latest redis-server --appendonly yes

下载 Windows 版的 Redis 管理器

Windows 版本的 Redis Desktop Manager 64位 2019.1(中文版) 下载地址 https://www.7down.com/soft/233274.html

官方正版最新版本下载地址 https://redisdesktop.com/download

另附 Redis 学习教程:

Redis 中文网 https://www.redis.net.cn/

.NET 使用 Redis 学习 地址(貌似这个教程版本过时了) https://www.cnblogs.com/cang12138/p/8884362.html

搭建 Master/Slaver 模式的 Redis 集群 https://blog.csdn.net/lupengfei1009/article/details/88323561#_154

使用 Redis Desktop Manager 连接 Redis

1565870987(1)

二,ASP.NET Core 使用分布式缓存

ASP.NET Core 中,支持使用多种数据库进行缓存,ASP.NET Core 提供了统一的接口给开发者使用。

IdistributedCache

ASP.NET Core 中,使用 IdistributedCache 为开发者提供统一的缓存使用接口,而不必关注使用的是何种数据库。

IdistributedCache]接口提供了以下方法操作的分布式的缓存实现中的项:

  • GetAsync –接受字符串键和检索缓存的项作为byte[]数组如果在缓存中找到。
  • SetAsync –中添加项 (作为byte[]数组) 到使用字符串键的缓存。
  • RefreshAsync –刷新缓存基于其密钥,重置其滑动到期超时值 (如果有) 中的项。
  • RemoveAsync –移除缓存项根据其字符串键值。

IdistributedCache 提供的常用方法如下:

方法 说明
Get(String) 获取Key(键)的值
GetAsync(String,CancellationToken) 异步获取键的值
Refresh(String) 刷新缓存
RefreshAsync(String,CancellationToken) Refreshes a value in the cache based on its key,resetting its sliding expiration timeout (if any).
Remove(String) 移除某个值
RemoveAsync(String,CancellationToken) Removes the value with the given key.
[Set(String,Byte],DistributedCacheEntryOptions) Sets a value with the given key.
[SetAsync(String,Byte],DistributedCacheEntryOptions,CancellationToken) Sets the value with the given key.

官方文档很详细https://docs.microsoft.com/zh-cn/dotnet/api/microsoft.extensions.caching.distributed.idistributedcache?view=aspnetcore-2.2

ASP.NET Core 中配置缓存

新建一个 ASP.NET Core WebApi 项目

Nuget 管理器安装

Microsoft.Extensions.Caching.StackExchangeRedis

ConfigureServices 中使用服务

services.AdddistributedMemoryCache();

配置 Redis 服务器

services.AddStackExchangeRedisCache(options =>
            {
                options.Configuration = "localhost:6379";
                options.InstanceName = "mvc";
            });

InstanceName 是你自定义的实例名称,创建缓存时会以此名称开头。

这样就配置好了。

使用缓存

修改默认生成的 ValuesController.cs。

注入缓存服务

private readonly IdistributedCache _cache;
        public ValuesController(IdistributedCache cache)
        {
            _cache = cache;
        }

设置缓存和使用缓存:

await _cache.GetAsync("{键名}");
_cache.SetAsync("键名",{值},{设置});

删除原来的方法,添加以下代码:

[HttpGet("Set")]
        public async Task<JsonResult> SetCache(string setkey,string setvalue)
        {

            string key = "key1";
            if (!string.IsNullOrEmpty(setkey))
                key = setkey;
            string value = DateTime.Now.ToLongTimeString();
            if (!string.IsNullOrEmpty(setvalue))
                value = setvalue;
            await _cache.SetStringAsync(key,value);
            return new JsonResult(new { Code = 200,Message = "设置缓存成功",Data = "key=" + key + "    value=" + value });
        }

        [HttpGet("Get")]
        public async Task<JsonResult> GetCache(string setkey)
        {
            string key = "key1";
            if (!string.IsNullOrEmpty(setkey))
                key = setkey;
            var value = await _cache.GetStringAsync(key);
            return new JsonResult(new { Code = 200,Data = "key=" + key + "    value=" + value });
        }

在 URL 添加 QueryString 可以设置缓存内容,如果没有带参数的话,就使用默认的值。

打开 https://localhost:5001/api/values/set 可以看到设置了默认值。

或者访问 https://localhost:5001/api/values/set?setkey=key11111&setvalue=asafesfdsreg

自定义设置缓存值。

1565872816(1)

打开 https://localhost:5001/api/values/get?setkey=key11111

可以获取缓存值。

设置缓存过期时间

使用 distributedCacheEntryOptions 可以设置缓存过期时间

distributedCacheEntryOptions 有三个属性,表示相对时间、绝对时间。

使用方法

[HttpGet("Set")]
        public async Task<JsonResult> SetCache(string setkey,string setvalue)
        {

            string key = "key1";
            if (!string.IsNullOrEmpty(setkey))
                key = setkey;
            string value = DateTime.Now.ToLongTimeString();
            if (!string.IsNullOrEmpty(setvalue))
                value = setvalue;

            var options = new distributedCacheEntryOptions()
            .SetSlidingExpiration(TimeSpan.FromSeconds(20));

            await _cache.SetStringAsync(key,value,options);
            return new JsonResult(new { Code = 200,Data = "key=" + key + "    value=" + value });
        }

缓存 20 秒,20秒过后此缓存将被清除。

C# redis StackExchange

C# redis StackExchange

1.Install-Package StackExchange -v 2.0.601

2.using StackExchange.Redis;

3.

static  void StackExchangeRedisDemo()
        {
            using(ConnectionMultiplexer redis=ConnectionMultiplexer.Connect("localhost,allowAdmin=true"))
            {
                var endPoint = redis.GetEndPoints().FirstOrDefault();
                var redisServer = redis.GetServer(endPoint);
                redisServer.FlushDatabase();
                IDatabase db = redis.GetDatabase(0);             
                
                DateTime dt = DateTime.Now;
                DateTime dtEnd = dt.AddSeconds(60);

                int num = 0; 
                List<string> keysList = new List<string>();
                while (DateTime.Now<dtEnd)
                {
                    num++;
                    string redisKey = Guid.NewGuid().ToString();
                    keysList.Add(redisKey);
                    db.StringSetAsync(redisKey, Guid.NewGuid().ToString());
                }
                ThreadPool.SetMinThreads(200, 200);
                System.Diagnostics.Debug.WriteLine($"redisServer.Keys().Count():{redisServer.Keys().Count()}\n,num:{num}");
            }
        }

 

C# StackExchange.Redis 用法总结

C# StackExchange.Redis 用法总结

原文: C# StackExchange.Redis 用法总结

阅读目录

  • 安装 StackExchange.Redis
  • 引用及初始化
  • String(字符串)
  • List(列表)
  • Hash(哈希)
  • 发布订阅
  • 事务
  • Batch 批量操作
  • Lock(分布式锁)
  • StackExchange.Redis 封装

安装 StackExchange.Redis

在 NuGet 中搜索 StackExchange.Redis 和 Newtonsoft.Json,直接点击按钮安装即可。

StackExchange.Redis 是 C# 操作 Redis 数据库的客户端。

Newtonsoft.Json 用来序列化 Josn 字符串及反序列化拿到对象。

回到顶部

引用及初始化

引用

using StackExchange.Redis;
using Newtonsoft.Json;

初始化 redis

ConnectionMultiplexer _conn = RedisConnectionHelp.Instance;//初始化
var database = _conn.GetDatabase(0);//指定连接的库 0
回到顶部

String(字符串)

String 是最常用的一种数据类型,普通的 key/value 存储都可以归为此类 。

一个 Key 对应一个 Value,string 类型是二进制安全的。Redis 的 string 可以包含任何数据,比如 jpg 图片(生成二进制)或者序列化的对象。

database.StringSet("name", "");//设置StringSet(key, value)
string str = database.StringGet("name");//结果:苍
database.StringSet("name_two", str, TimeSpan.FromSeconds(10));//设置时间,10s后过期。

存对象(对象需要序列化转成字符串,再存进库中)

取对象(反序列化)

复制代码
//创建对
Demo demo = new Demo()
{
    Name = "",
    Age = 18,
    Height = 1.83
};
string demojson = JsonConvert.SerializeObject(demo);//序列化
database.StringSet("model", demojson);

string model = database.StringGet("model");
demo = JsonConvert.DeserializeObject<Demo>(model);//反序列化
复制代码

StringIncrement 增量、StringDecrement 减量(默认值同为1)

复制代码
double increment = 0;
double decrement = 0;
for (int i = 0; i < 3; i++)
{
    increment = database.StringIncrement("StringIncrement", 2);//增量,每次+2
}
for (int i = 0; i < 3; i++)
{
    decrement = database.StringDecrement("StringIncrement");//减量,每次-1
}
复制代码
回到顶部

List(列表)

Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部或者尾部。

一个列表最多可以包含 232 - 1 个元素 (4294967295, 每个列表超过 40 亿个元素)。

复制代码
for (int i = 0; i < 10; i++)
{
    database.ListRightPush("list", i);//从底部插入数据
}
for (int i = 10; i < 20; i++)
{
    database.ListLeftPush("list", i);//从顶部插入数据
}
var length = database.ListLength("list");//长度 20

var rightPop = database.ListRightPop("list");//从底部拿出数据

var leftpop = database.ListLeftPop("list");//从顶部拿出数据

var list = database.ListRange("list");
复制代码

回到顶部

Hash(哈希)

Redis hash 是一个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象。相对于将对象的每个字段存成单个 string 类型。一个对象存储在 hash 类型中会占用更少的内存,并且可以更方便的存取整个对象。

Redis 中每个 hash 可以存储 232 - 1 键值对(40多亿)。

Hash 的存储,给我的感觉类似于关系型数据库。以下面的例子为例,存储一个 user 对象(关系型数据库里的表名), cang、shan、yun (关系型数据库里的数据的主键、唯一值),json(字段

复制代码
string json = JsonConvert.SerializeObject(demo);//序列化
database.HashSet("user", "cang", json);
database.HashSet("user", "shan", json);
database.HashSet("user", "yun", json);

//获取Model
string hashcang = database.HashGet("user", "cang"); demo = JsonConvert.DeserializeObject<Demo>(hashcang);//反序列化 //获取List RedisValue[] values = database.HashValues("user");//获取所有value IList<Demo> demolist = new List<Demo>(); foreach (var item in values) { Demo hashmodel = JsonConvert.DeserializeObject<Demo>(item); demolist.Add(hashmodel); }
复制代码
回到顶部

发布订阅

Redis 发布订阅 (pub/sub) 是一种消息通信模式,可以用于消息的传输,Redis 的发布订阅机制包括三个部分,发布者,订阅者和 Channel。适宜做在线聊天、消息推送等。

发布者和订阅者都是 Redis 客户端,Channel 则为 Redis 服务器端,发布者将消息发送到某个的频道,订阅了这个频道的订阅者就能接收到这条消息,客户端可以订阅任意数量的频道。

复制代码
ISubscriber sub = _conn.GetSubscriber();

//订阅 Channel1 频道
sub.Subscribe("Channel1", new Action<RedisChannel, RedisValue>((channel, message) =>
{
    Console.WriteLine("Channel1" + " 订阅收到消息:" + message);
}));

for (int i = 0; i < 10; i++)
{
    sub.Publish("Channel1", "msg" + i);//向频道 Channel1 发送信息
    if (i == 2)
    {
        sub.Unsubscribe("Channel1");//取消订阅
    }
}
复制代码

因为当 i == 2 的时候取消订阅,所以收到的订阅消息只有3条。

回到顶部

事务

事物开启后,会在调用 Execute 方法时把相应的命令操作封装成一个请求发送给 Redis 一起执行。

这里通过 CreateTransaction 函数(multi)来创建一个事物,调用其 Execute 函数(exec)提交事物。

其中的 "Condition.StringEqual("name", name)" 就相当于 Redis 命令中的 watch name。

复制代码
string name = database.StringGet("name");
string age = database.StringGet("age");
var tran = database.CreateTransaction();//创建事物
tran.AddCondition(Condition.StringEqual("name", name));//乐观锁
tran.StringSetAsync("name", "海");
tran.StringSetAsync("age", 25);
database.StringSet("name", "Cang");//此时更改 name 值,提交事物的时候会失败。
bool committed = tran.Execute();//提交事物,true成功,false回滚。
复制代码

因为提交事物的过程中,name 值被修改,所以造成了回滚,所有给 name 赋值海,age 赋值25都失败了。

回到顶部

Batch 批量操作

batch 会把所需要执行的命令打包成一条请求发到 Redis,然后一起等待返回结果。减少网络开销。

复制代码
var batch = database.CreateBatch();

//批量写
Task t1 = batch.StringSetAsync("name", "");
Task t2 = batch.StringSetAsync("age", 22);
batch.Execute();
Task.WaitAll(t1, t2);
Console.WriteLine("Age:" + database.StringGet("age"));
Console.WriteLine("Name:" + database.StringGet("name"));
            
//批量写
for (int i = 0; i < 100000; i++)
{
    batch.StringSetAsync("age" + i, i);
}
batch.Execute();

//批量读
List<Task<RedisValue>> valueList = new List<Task<RedisValue>>();
for (int i = 0; i < 10000; i++)
{
    Task<RedisValue> tres = batch.StringGetAsync("age" + i);
    valueList.Add(tres);
}
batch.Execute();
foreach (var redisValue in valueList)
{
string value = redisValue.Result;//取出对应的value值
}
复制代码
回到顶部

Lock(分布式锁)

由于 Redis 是单线程模型,命令操作原子性,所以利用这个特性可以很容易的实现分布式锁。

复制代码
RedisValue token = Environment.MachineName;
//lock_key表示的是redis数据库中该锁的名称,不可重复。 
//token用来标识谁拥有该锁并用来释放锁。
//TimeSpan表示该锁的有效时间。10秒后自动释放,避免死锁。
if (database.LockTake("lock_key", token, TimeSpan.FromSeconds(10))) { try { //TODO:开始做你需要的事情 Thread.Sleep(5000); } finally { database.LockRelease("lock_key", token);//释放锁 } }
复制代码
回到顶部

StackExchange.Redis 封装

里面是封装及测试代码

链接: https://pan.baidu.com/s/1rT9z567MVtfzQtnvdUxffw 密码: 5k1b

环境:vs2013 + .NET framework 4.5


相关文章:Redis Windows版下载与安装

              Redis 可视化工具 Redis Desktop Manager

              Redis 主从配置(Windows版)

关于Stackexchange.Redis的开火和遗忘保证交货吗?的介绍现已完结,谢谢您的耐心阅读,如果想了解更多关于.net core使用redis基于StackExchange.Redis、ASP.NET Core 使用 Redis 实现分布式缓存:Docker、IDistributedCache、StackExchangeRedis、C# redis StackExchange、C# StackExchange.Redis 用法总结的相关知识,请在本站寻找。

本文标签: