2020年11月16日星期一

Redis分布式缓存系列(二)

本系列将和大家分享Redis分布式缓存,本章主要简单介绍下Redis中的String类型,以及如何使用Redis解决订单秒杀超卖问题。

本系列将和大家分享Redis分布式缓存,本章主要简单介绍下Redis中的String类型,以及如何使用Redis解决订单秒杀超卖问题。

Redis中5种数据结构之String类型:key-value的缓存,支持过期,value不超过512M。

Redis是单线程的,比如SetAll & AppendToValue & GetValues & GetAndSetValue & IncrementValue & IncrementValueBy等等,这些看上去像是组合命令,但实际上是一个具体的命令,是一个原子性的命令,不可能出现中间状态,可以应对一些并发情况。下面我们直接通过代码来看下具体使用。

首先来看下Demo的项目结构:

此处推荐使用的是ServiceStack包,虽然它是收费的,有1小时3600次请求限制,但是它是开源的,可以将它的源码下载下来破解后使用,网上应该有挺多相关资料,有兴趣的可以去了解一波。

一、Redis中与String类型相关的API

首先先来看下Redis客户端的初始化工作:

using System;namespace TianYa.Redis.Init{ /// <summary> /// redis配置文件信息 /// 也可以放到配置文件去 /// </summary> public sealed class RedisConfigInfo {  /// <summary>  /// 可写的Redis链接地址  /// format:ip1,ip2  ///   /// 默认6379端口  /// </summary>  public string WriteServerList = "127.0.0.1:6379";  /// <summary>  /// 可读的Redis链接地址  /// format:ip1,ip2  ///   /// 默认6379端口  /// </summary>  public string ReadServerList = "127.0.0.1:6379";  /// <summary>  /// 最大写链接数  /// </summary>  public int MaxWritePoolSize = 60;  /// <summary>  /// 最大读链接数  /// </summary>  public int MaxReadPoolSize = 60;  /// <summary>  /// 本地缓存到期时间,单位:秒  /// </summary>  public int LocalCacheTime = 180;  /// <summary>  /// 自动重启  /// </summary>  public bool AutoStart = true;  /// <summary>  /// 是否记录日志,该设置仅用于排查redis运行时出现的问题,  /// 如redis工作正常,请关闭该项  /// </summary>  public bool RecordeLog = false; }}
using ServiceStack.Redis;namespace TianYa.Redis.Init{ /// <summary> /// Redis管理中心 /// </summary> public class RedisManager {  /// <summary>  /// Redis配置文件信息  /// </summary>  private static RedisConfigInfo _redisConfigInfo = new RedisConfigInfo();  /// <summary>  /// Redis客户端池化管理  /// </summary>  private static PooledRedisClientManager _prcManager;  /// <summary>  /// 静态构造方法,初始化链接池管理对象  /// </summary>  static RedisManager()  {   CreateManager();  }  /// <summary>  /// 创建链接池管理对象  /// </summary>  private static void CreateManager()  {   string[] writeServerConStr = _redisConfigInfo.WriteServerList.Split(',');   string[] readServerConStr = _redisConfigInfo.ReadServerList.Split(',');   _prcManager = new PooledRedisClientManager(readServerConStr, writeServerConStr,    new RedisClientManagerConfig    {     MaxWritePoolSize = _redisConfigInfo.MaxWritePoolSize,     MaxReadPoolSize = _redisConfigInfo.MaxReadPoolSize,     AutoStart = _redisConfigInfo.AutoStart,    });  }  /// <summary>  /// 客户端缓存操作对象  /// </summary>  public static IRedisClient GetClient()  {   return _prcManager.GetClient();  } }}
using System;using TianYa.Redis.Init;using ServiceStack.Redis;namespace TianYa.Redis.Service{ /// <summary> /// redis操作的基类 /// </summary> public abstract class RedisBase : IDisposable {  /// <summary>  /// Redis客户端  /// </summary>  protected IRedisClient _redisClient { get; private set; }  /// <summary>  /// 构造函数  /// </summary>  public RedisBase()  {   this._redisClient = RedisManager.GetClient();  }  private bool _disposed = false;  protected virtual void Dispose(bool disposing)  {   if (!this._disposed)   {    if (disposing)    {     _redisClient.Dispose();     _redisClient = null;    }   }   this._disposed = true;  }  public void Dispose()  {   Dispose(true);   GC.SuppressFinalize(this);  }  /// <summary>  /// Redis事务处理示例  /// </summary>  public void Transcation()  {   using (IRedisTransaction irt = this._redisClient.CreateTransaction())   {    try    {     irt.QueueCommand(r => r.Set("key", 20));     irt.QueueCommand(r => r.Increment("key", 1));     irt.Commit(); //事务提交    }    catch (Exception ex)    {     irt.Rollback(); //事务回滚     throw ex;    }   }  }  /// <summary>  /// 清除全部数据 请小心  /// </summary>  public virtual void FlushAll()  {   _redisClient.FlushAll();  }  /// <summary>  /// 保存数据DB文件到硬盘  /// </summary>  public void Save()  {   _redisClient.Save(); //阻塞式Save  }  /// <summary>  /// 异步保存数据DB文件到硬盘  /// </summary>  public void SaveAsync()  {   _redisClient.SaveAsync(); //异步Save  } }}

下面直接给大家Show一波Redis中与String类型相关的API:

using System;using System.Collections.Generic;namespace TianYa.Redis.Service{ /// <summary> /// key-value 键值对 value可以是序列化的数据 (字符串) /// </summary> public class RedisStringService : RedisBase {  #region 赋值  /// <summary>  /// 设置永久缓存  /// </summary>  /// <param name="key">存储的键</param>  /// <param name="value">存储的值</param>  /// <returns></returns>  public bool Set(string key, string value)  {   return base._redisClient.Set(key, value);  }  /// <summary>  /// 设置永久缓存  /// </summary>  /// <param name="key">存储的键</param>  /// <param name="value">存储的值</param>  /// <returns></returns>  public bool Set<T>(string key, T value)  {   return base._redisClient.Set<T>(key, value);  }  /// <summary>  /// 带有过期时间的缓存  /// </summary>  /// <param name="key">存储的键</param>  /// <param name="value">存储的值</param>  /// <param name="expireTime">过期时间</param>  /// <returns></returns>  public bool Set(string key, string value, DateTime expireTime)  {   return base._redisClient.Set(key, value, expireTime);  }  /// <summary>  /// 带有过期时间的缓存  /// </summary>  /// <param name="key">存储的键</param>  /// <param name="value">存储的值</param>  /// <param name="expireTime">过期时间</param>  /// <returns></returns>  public bool Set<T>(string key, T value, DateTime expireTime)  {   return base._redisClient.Set<T>(key, value, expireTime);  }  /// <summary>  /// 带有过期时间的缓存  /// </summary>  /// <param name="key">存储的键</param>  /// <param name="value">存储的值</param>  /// <param name="expireTime">过期时间</param>  /// <returns></returns>  public bool Set<T>(string key, T value, TimeSpan expireTime)  {   return base._redisClient.Set<T>(key, value, expireTime);  }  /// <summary>  /// 设置多个key/value  /// </summary>  public void SetAll(Dictionary<string, string> dic)  {   base._redisClient.SetAll(dic);  }  

没有评论:

发表评论