• .Net Core3.0 WebApi 八:使用Redis做数据缓存


    .Net Core3.0 WebApi 目录

    Redis介绍

    之前的随笔中,也有关于Redis的介绍。这里就简单介绍一下。

    简单来说 redis 就是一个数据库,不过与传统数据库不同的是 redis 的数据是存在内存中的,所以读写速度非常快,因此 redis 被广泛应用于缓存方向。另外,redis 也经常用来做分布式锁。redis 提供了多种数据类型来支持不同的业务场景。除此之外,redis 支持事务 、持久化、LUA脚本、LRU驱动事件、多种集群方案。

    为什么要用 redis?/为什么要用缓存?

    主要从“高性能”和“高并发”这两点来看待这个问题。

    高性能:

    假如用户第一次访问数据库中的某些数据。这个过程会比较慢,因为是从硬盘上读取的。将该用户访问的数据存在缓存中,这样下一次再访问这些数据的时候就可以直接从缓存中获取了。操作缓存就是直接操作内存,所以速度相当快。如果数据库中的对应数据改变的之后,同步改变缓存中相应的数据即可!

    高并发:

    直接操作缓存能够承受的请求是远远大于直接访问数据库的,所以我们可以考虑把数据库中的部分数据转移到缓存中去,这样用户的一部分请求会直接到缓存这里而不用经过数据库。

    什么数据需要存Redis

    欢迎补充:

    1.任何可丢失数据

    2.不经常变动的数据

    Redis安装配置

    安装:www.baidu.com,网上一大堆。这里主要配置一下redis连接字符串,在appsetting.json添加Redis配置。

    {
      "Logging": {
        "LogLevel": {
          "Default": "Information",
          "Microsoft": "Warning",
          "Microsoft.Hosting.Lifetime": "Information"
        }
      },
      "AllowedHosts": "*",
      "ConnectionStrings": {
        "ConnectionString": "Data Source=127.0.0.1;Initial Catalog=db;User ID=uid;Password=123456;Pooling=True;Max Pool Size=512;Connect Timeout=500;",
        "JwtSetting": {
          "Issuer": "jwtIssuer", //颁发者
          "Audience": "jwtAudience", //可以给哪些客户端使用
          "SecretKey": "chuangqianmingyueguang" //加密的Key
        },
        "RedisCaching": {
          "Enabled": true,
          "ConnectionString": "127.0.0.1:6379"
        }
      }
    }

    自定义序列化帮助类

    Infrastructure的Helpers文件夹中,添加SerializeHelper.cs 对象序列化操作

    namespace WebApi.Core.Infrastructure.Helpers
    {
        public class SerializeHelper
        {
            /// <summary>
            /// 序列化
            /// </summary>
            /// <param name="item"></param>
            /// <returns></returns>
            public static byte[] Serialize(object item)
            {
                var jsonString = JsonConvert.SerializeObject(item);
    
                return Encoding.UTF8.GetBytes(jsonString);
            }
            /// <summary>
            /// 反序列化
            /// </summary>
            /// <typeparam name="TEntity"></typeparam>
            /// <param name="value"></param>
            /// <returns></returns>
            public static TEntity Deserialize<TEntity>(byte[] value)
            {
                if (value == null)
                {
                    return default(TEntity);
                }
                var jsonString = Encoding.UTF8.GetString(value);
                return JsonConvert.DeserializeObject<TEntity>(jsonString);
            }
        }
    }

    定义Redis接口和实现类

    Infrastructure类库中,新建Redis文件夹,新建IRedisCacheManager接口和RedisCacheManager类,并引用Nuget包StackExchange.Redis

    namespace WebApi.Core.Infrastructure.Redis
    {
        public class RedisCacheManager : IRedisCacheManager
        {
            private readonly string redisConnenctionString;
            public volatile ConnectionMultiplexer redisConnection;
            private readonly object redisConnectionLock = new object();
            public RedisCacheManager()
            {
                string redisConfiguration = ConfigHelper.GetSectionValue("ConnectionStrings:RedisCaching:ConnectionString");//获取连接字符串
    
                if (string.IsNullOrWhiteSpace(redisConfiguration))
                {
                    throw new ArgumentException("redis config is empty", nameof(redisConfiguration));
                }
                this.redisConnenctionString = redisConfiguration;
                this.redisConnection = GetRedisConnection();
            }
    
            /// <summary>
            /// 核心代码,获取连接实例
            /// 通过双if 夹lock的方式,实现单例模式
            /// </summary>
            /// <returns></returns>
            private ConnectionMultiplexer GetRedisConnection()
            {
                //如果已经连接实例,直接返回
                if (this.redisConnection != null && this.redisConnection.IsConnected)
                {
                    return this.redisConnection;
                }
                //加锁,防止异步编程中,出现单例无效的问题
                lock (redisConnectionLock)
                {
                    if (this.redisConnection != null)
                    {
                        //释放redis连接
                        this.redisConnection.Dispose();
                    }
                    try
                    {
                        this.redisConnection = ConnectionMultiplexer.Connect(redisConnenctionString);
                    }
                    catch (Exception)
                    {
    
                        throw new Exception("Redis服务未启用,请开启该服务");
                    }
                }
                return this.redisConnection;
            }
    
            public void Clear()
            {
                foreach (var endPoint in this.GetRedisConnection().GetEndPoints())
                {
                    var server = this.GetRedisConnection().GetServer(endPoint);
                    foreach (var key in server.Keys())
                    {
                        redisConnection.GetDatabase().KeyDelete(key);
                    }
                }
            }
    
            public bool Get(string key)
            {
                return redisConnection.GetDatabase().KeyExists(key);
            }
    
            public string GetValue(string key)
            {
                return redisConnection.GetDatabase().StringGet(key);
            }
    
            public TEntity Get<TEntity>(string key)
            {
                var value = redisConnection.GetDatabase().StringGet(key);
                if (value.HasValue)
                {
                    //需要用的反序列化,将Redis存储的Byte[],进行反序列化
                    return SerializeHelper.Deserialize<TEntity>(value);
                }
                else
                {
                    return default(TEntity);
                }
            }
    
            public void Remove(string key)
            {
                redisConnection.GetDatabase().KeyDelete(key);
            }
    
            public void Set(string key, object value, TimeSpan cacheTime)
            {
                if (value != null)
                {
                    //序列化,将object值生成RedisValue
                    redisConnection.GetDatabase().StringSet(key, SerializeHelper.Serialize(value), cacheTime);
                }
            }
    
            public bool SetValue(string key, byte[] value)
            {
                return redisConnection.GetDatabase().StringSet(key, value, TimeSpan.FromSeconds(120));
            }
    
        }
    }

    将Redis服务注入到容器中

    将redis接口和类 在ConfigureServices中 进行注入:

    //注册Redis
    services.AddSingleton<IRedisCacheManager, RedisCacheManager>();

    控制器中调用

    通过构造函数把IRedisCacheManager和UserRepository注入进去,然后新加一个接口。

    /// <summary>
    /// 测试Redis
    /// </summary>
    /// <returns></returns>
    [HttpGet]
    public async Task<IActionResult> Redis(int id)
    {
    
        var key = $"Redis{id}";
        UserNew user = new UserNew();
        if (_redisCacheManager.Get<object>(key) != null)
        {
            user = _redisCacheManager.Get<UserNew>(key);
        }
        else
        {
            user = new UserNew
            {
                UserId = id,
                UserName = "bingle",
                Age = 18
            };
            _redisCacheManager.Set(key, user, TimeSpan.FromHours(2));//缓存2小时
        }
    
        return Ok(user);
    }

    运行项目,测试接口。测试接口之前,需要先把Redis服务器开启。

    Redis缓存NoSQL  详细的介绍了Redis,docker下安装Redis 以及docker下安装Redis

     第一次执行,这个key下是没有值的,所以,会走下面的代码,进行缓存。

     得到这样的响应结果。我们再来调试一次,看看。

     这次会从缓存中取值。得到的结果,和上面的结果一样。

  • 相关阅读:
    Win8系统 Python安装
    一些安卓开源框架整理
    Android 媒体键监听以及模拟媒体键盘的实现 demo
    android View 自动 GONE 问题
    Android 定时器TimerTask 简单使用
    关于Android studio 相对 eclipse 优点
    Java序列化与反序列化
    android shape的使用 边框
    Android Studio 修改 包名 package name
    Android WebView Long Press长按保存图片到手机
  • 原文地址:https://www.cnblogs.com/taotaozhuanyong/p/13794499.html
Copyright © 2020-2023  润新知