c# - 在 Azure Redis 缓存中插入或删除值时是否需要在代码级别进行同步?
问题描述
我正在使用以下单例类从 Azure Redis 缓存中获取/设置/删除值,以完成我的一项个人开发工作。
using StackExchange.Redis;
using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
namespace PoC
{
public sealed class CacheManager
{
public static object mutex = new object();
public static string EndPoint { get; set; }
public static string Password { get; set; }
public static bool UseSsl { get; set; }
public static int ConnectRetry { get; set; }
public static int KeepAlive { get; set; }
public static int ConnectTimeout { get; set; }
private static ConfigurationOptions ConfigurationOptions;
private static readonly CacheManager instance = new CacheManager();
// Explicit static constructor to tell C# compiler
// not to mark type as beforefieldinit
static CacheManager() { }
private CacheManager()
{
ConfigurationOptions = new ConfigurationOptions
{
Password = Password,
Ssl = UseSsl,
AbortOnConnectFail = false,
ConnectRetry = ConnectRetry,
KeepAlive = KeepAlive,
ConnectTimeout = ConnectTimeout
};
}
public static CacheManager Instance { get { return instance; } }
public static string ConnectionString { get; set; }
Lazy<ConnectionMultiplexer> lazyConnection = new Lazy<ConnectionMultiplexer>(() =>
{
return ConnectionMultiplexer.Connect(ConfigurationOptions);
});
IDatabase Database => lazyConnection.Value.GetDatabase();
public void Set<T>(string key, T value)
{
lock (mutex)
{
Database.StringSet(key, ToByteArray(value));
}
}
public T Get<T>(string key)
{
T result = FromByteArray<T>(Database.StringGet(key));
return result;
}
public bool Remove(string key)
{
lock (mutex)
{
var removed = Database.KeyDelete(key);
return removed;
}
}
public byte[] ToByteArray<T>(T obj)
{
if (obj == null)
return null;
BinaryFormatter bf = new BinaryFormatter();
using (MemoryStream ms = new MemoryStream())
{
bf.Serialize(ms, obj);
return ms.ToArray();
}
}
public T FromByteArray<T>(byte[] data)
{
if (data == null)
return default(T);
BinaryFormatter bf = new BinaryFormatter();
using (MemoryStream ms = new MemoryStream(data))
{
object obj = bf.Deserialize(ms);
return (T)obj;
}
}
}
}
在这里,我在将值插入数据库或从数据库中删除值时使用了锁。但是从下面的帖子我知道Redis是一个单线程数据库,所有的操作都是原子的——
更新项目时 Azure Redis 缓存中是否有任何锁定机制?
所以我认为我使用的锁是不必要的,可能会导致一些性能问题。如果我错了,请纠正我。我在Application_Start
事件中设置了一次变量(端点、密码等)。将不胜感激。
解决方案
您可以学习如何WATCH
在 Redis 中使用。https://stackexchange.github.io/StackExchange.Redis/Transactions.html
WATCH key
isFieldExists = HEXISTS key, field
if isFieldExists is 1
MULTI
HSET key, field, value
EXEC
else
UNWATCH
return isFieldExists
例子:
var newId = CreateNewId();
var tran = db.CreateTransaction();
tran.AddCondition(Condition.HashNotExists(custKey, "UniqueID"));
tran.HashSetAsync(custKey, "UniqueID", newId);
bool committed = tran.Execute();
推荐阅读
- r - R - 使用数据框作为“散列图”
- android - Android资源编译失败错误:资源'attr/layout_anchorGravity'与配置''的重复值
- rest - OData 获取单个属性:~/entityset/key/navigation/property
- javascript - 当我在 document.ready() 中没有模型时如何绑定模型
- scala - 在 Snappydata 中创建 20-30 个表后获取 com.gemstone.gemfire.cache.LockTimeoutException
- python - 如何修改服务器上的json?
- elasticsearch - 如何在嵌套聚合中使用过滤器?
- xslt-1.0 - 如何分别显示不同节点组中的子节点?
- javascript - Node-RED 发送多个 msg 只返回第一个 msg
- php - 使用作曲家时如何仅在特定文件上制作“require”-config文件