示例介绍

示例1:借助Redis实现购物车功能

示例2:Redis实现网页缓存和数据缓存

借助Redis实现购物车功能

每个用户的购物车都是一个散列,散列存储了商品ID与商品订购数量之间的映射。订购商品时,对购物车进行更新:如果用户订购某件商品的数量大于0,那么将这件商品的ID以及用户订购该商品的数量添加到散列里面,如果用户购买的商品已经存在散列里面,那么新的订购数量会覆盖已有的订购数量;相反,如果用户订购某件商品数量不大于0,那么程序将从散列里面移除该条目。

由于整个示例分Controller和WebApi两部分,在不考虑封装Redis操作的情况下提取Redis连接字符串到appSetting.json中

  1. "ConnectionStrings": {
  2. "Redis": "localhost,abortConnect=false"
  3. },

保存用户购物查数据示例代码:

  1. [HttpGet("UpdateCart")]
  2. public string UpdateCart(string token,string item,int count)
  3. {
  4. var key = $"cart:{token}";
  5. using (var redis = ConnectionMultiplexer.Connect(redisConnectionStr))
  6. {
  7. var db = redis.GetDatabase();
  8. //更新购物车数据
  9. if (count <= 0)
  10. {
  11. db.HashDeleteAsync(key, item);
  12. }
  13. else
  14. {
  15. db.HashSetAsync(key, item,count);
  16. }
  17. }
  18.  
  19. return "更新购物车成功";
  20. }

Redis实现网页缓存和数据缓存

针对不会频繁更新得动态网页或Ajax返回的数据可以缓存在Redis中,减少与数据库的交互提升系统效应效率。

该示例只是为了演示借助Reids实现页面缓存和数据缓存效果,实际使用中可通过ResponseCache特性实现缓存。

详细介绍:https://docs.microsoft.com/en-us/aspnet/core/performance/caching/response?view=aspnetcore-5.0

网页数据缓存

新建示例项目时为WebApi项目,修改Startup类添加Web Mvc支持。

ConfigureServices方法中修改services.AddControllers()services.AddControllersWithViews()

Configure方法中app.UseEndpoints修改为如下代码

  1. app.UseEndpoints(endpoints =>
  2. {
  3. endpoints.MapControllerRoute(
  4. name: "default",
  5. pattern: "{controller=Home}/{action=Index}/{id?}");
  6. });

定义中间件类RedisCacheMiddleware,用来缓存网页页面

  1. public class RedisCacheMiddleware
  2. {
  3.  
  4. private readonly RequestDelegate _next;
  5.  
  6. public IConfiguration Configuration { get; }
  7.  
  8. public RedisCacheMiddleware(RequestDelegate next, IConfiguration configuration)
  9. {
  10. _next = next;
  11. Configuration = configuration;
  12. }
  13.  
  14. public async Task InvokeAsync(HttpContext context)
  15. {
  16.  
  17. var path = context.Request.Path.Value.ToLower();
  18.  
  19. if (path == "/home" || path == "/home/index")
  20. {
  21.  
  22. var responseContent = "";
  23.  
  24. //Copy a pointer to the original response body stream
  25. var originalBodyStream = context.Response.Body;
  26.  
  27. using (var redis = ConnectionMultiplexer.Connect(Configuration.GetConnectionString("Redis")))
  28. {
  29. var db = redis.GetDatabase();
  30. if (db.KeyExists(path))
  31. {
  32. responseContent = db.StringGet(path);
  33. await RespondWithIndexHtml(context.Response, responseContent);
  34. return;
  35. }
  36. else
  37. {
  38. using (var responseBody = new MemoryStream())
  39. {
  40. //...and use that for the temporary response body
  41. context.Response.Body = responseBody;
  42.  
  43. //Continue down the Middleware pipeline, eventually returning to this class
  44. await _next(context);
  45.  
  46. //Format the response from the server
  47. responseContent = await FormatResponse(context.Response);
  48.  
  49. //Copy the contents of the new memory stream (which contains the response) to the original stream, which is then returned to the client.
  50. await responseBody.CopyToAsync(originalBodyStream);
  51. }
  52.  
  53. db.StringSet(path, responseContent, expiry: TimeSpan.FromSeconds(30));
  54. }
  55. }
  56.  
  57. }
  58.  
  59. // Call the next delegate/middleware in the pipeline
  60. await _next(context);
  61. }
  62.  
  63. private async Task RespondWithIndexHtml(HttpResponse response,string html)
  64. {
  65. response.StatusCode = 200;
  66. response.ContentType = "text/html";
  67.  
  68. await response.WriteAsync(html, Encoding.UTF8);
  69. }
  70.  
  71. private async Task<string> FormatResponse(HttpResponse response)
  72. {
  73. //We need to read the response stream from the beginning...
  74. response.Body.Seek(0, SeekOrigin.Begin);
  75.  
  76. //...and copy it into a string
  77. string text = await new StreamReader(response.Body).ReadToEndAsync();
  78.  
  79. //We need to reset the reader for the response so that the client can read it.
  80. response.Body.Seek(0, SeekOrigin.Begin);
  81.  
  82. //Return the string for the response
  83. return text;
  84. }
  85.  
  86. }

添加中间件调用

  1. app.UseMiddleware<RedisCacheMiddleware>();

运行效果如图:

网页上的时间会每30秒更新一次。

.Net Core提供的响应缓存中间件:https://docs.microsoft.com/zh-cn/aspnet/core/performance/caching/middleware?view=aspnetcore-5.0

Ajax数据缓存

本例只是简单的数据存储,实际使用中可编写单独的服务,让这个服务将指定的数据缓存到Redis里面,并不定期地对这些缓存进行更新。

示例代码

  1. [HttpGet("GetDateTime")]
  2. public string GetDateTime()
  3. {
  4. var dateTime = "";
  5. var key = "data:datetime";
  6. using (var redis = ConnectionMultiplexer.Connect(redisConnectionStr))
  7. {
  8. var db = redis.GetDatabase();
  9. if (db.KeyExists(key))
  10. {
  11. dateTime = db.StringGet(key);
  12. }
  13. else
  14. {
  15. dateTime = DateTimeOffset.Now.ToString("yyyy-MM-dd HH:mm:ss");
  16. db.StringSet(key, dateTime,expiry:TimeSpan.FromSeconds(5));
  17. }
  18. }
  19.  
  20. return dateTime;
  21. }

参考资料

Using Middleware in .NET 5.0 to Log Requests and Responses

如何在 asp.net core 的中间件中返回具体的页面

Swashbuckle.AspNetCore.ReDoc/ReDocMiddleware.cs

.Net Redis实战——使用Redis构建Web应用的更多相关文章

  1. Redis实战之Redis + Jedis

    用Memcached,对于缓存对象大小有要求,单个对象不得大于1MB,且不支持复杂的数据类型,譬如SET 等.基于这些限制,有必要考虑Redis! 相关链接: Redis实战 Redis实战之Redi ...

  2. Redis实战之Redis + Jedis[转]

    http://blog.csdn.net/it_man/article/details/9730605 2013-08-03 11:01 1786人阅读 评论(0) 收藏 举报   目录(?)[-] ...

  3. Redis实战:如何构建类微博的亿级社交平台

    微博及 Twitter 这两大社交平台都重度依赖 Redis 来承载海量用户访问.本文介绍如何使用 Redis 来设计一个社交系统,以及如何扩展 Redis 让其能够承载上亿用户的访问规模. 虽然单台 ...

  4. 实战案例--Grunt构建Web程序

    GruntJS构建Web程序.使用Gruntjs来搭建一个前端项目,然后使用grunt合并,压缩JS文件,熟练了node.js安装和grunt.js安装后,接下来来实战一个案例,案例是根据snandy ...

  5. Redis实战总结-Redis的高可用性

    在之前的博客<Redis实战总结-配置.持久化.复制>给出了一种Redis主从复制机制,简单地实现了Redis高可用.然后,如果Master服务器宕机,会导致整个Redis瘫痪,这种方式的 ...

  6. Redis 实战 —— 05. Redis 其他命令简介

    发布与订阅 P52 Redis 实现了发布与订阅(publish/subscribe)模式,又称 pub/sub 模式(与设计模式中的观察者模式类似).订阅者负责订阅频道,发送者负责向频道发送二进制字 ...

  7. Redis 实战 —— 14. Redis 的 Lua 脚本编程

    简介 Redis 从 2.6 版本开始引入使用 Lua 编程语言进行的服务器端脚本编程功能,这个功能可以让用户直接在 Redis 内部执行各种操作,从而达到简化代码并提高性能的作用. P248 在不编 ...

  8. 分布式缓存技术redis学习系列(五)——redis实战(redis与spring整合,分布式锁实现)

    本文是redis学习系列的第五篇,点击下面链接可回看系列文章 <redis简介以及linux上的安装> <详细讲解redis数据结构(内存模型)以及常用命令> <redi ...

  9. 分布式缓存技术redis系列(五)——redis实战(redis与spring整合,分布式锁实现)

    本文是redis学习系列的第五篇,点击下面链接可回看系列文章 <redis简介以及linux上的安装> <详细讲解redis数据结构(内存模型)以及常用命令> <redi ...

随机推荐

  1. volatile修饰全局变量,可以保证并发安全吗?

    今天被人问到volatile能不能保证并发安全? 呵,这能难倒我? 上代码: //电脑太好,100线程起步~public class ThreadTest { private static volat ...

  2. reset 去掉margin和padding的 默认代码,其余根据自己的情况做调整

    body, dl, dd, h2, h3, h4, h5, h6, p, form{margin:0;} ol,li,ul{margin:0; padding:0;} h1{margin:10px 0 ...

  3. POJ2406 KMP前缀周期

    题意:       给你一个字符串,长度小于1百万,问你他最多可以拆成集合相同字符串,例如abcabcabc 可以拆成3个abc,所以输出3. 思路:       这个是比较常规的next应用,首先假 ...

  4. Python脚本暴力破解SSH口令以及构建僵尸网络(pxssh)

    目录 暴力破解SSH口令 SSH远端执行命令 构建僵尸网络 环境:Kali Linux  python 2.7.13 暴力破解SSH口令 Pxssh是pexpect库的ssh专用脚本,他能用预先写好的 ...

  5. Windows中的用户和组以及用户密码处理

    目录 用户帐户 Windows 默认账户 Windows 内置用户账户 查看.创建和删除账户 组账户 内置组账户 组的查看.创建和删除 Windows中对用户密码的处理 LM-hash NTLM-ha ...

  6. C#-获取CPUID

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.D ...

  7. Linux Limit相关内容设置大全(值得收藏)

    目录 一. /etc/security/limits.conf 详解 /etc/security/limits.conf 配置解析 /etc/security/limits.d/目录 二. ulimi ...

  8. 上手 WebRTC DTLS 遇到很多 BUG?浅谈 DTLS Fragment

    上一篇<详解 WebRTC 传输安全机制:一文读懂 DTLS 协议>详细阐述了 DTLS.本文将结合 DTLS 开发中遇到的问题,详细解读 DTLS 的一些基础概念以及 Fragment ...

  9. python分析《三国演义》,谁才是这部书的绝对主角(包含统计指定角色的方法)

    前面分析统计了金庸名著<倚天屠龙记>中人物按照出现次数并排序 https://www.cnblogs.com/becks/p/11421214.html 然后使用pyecharts,统计B ...

  10. 判断标准I/O的缓冲区类型

    #include <stdio.h> void pr_stdio(const char *, FILE *); int main() { FILE *fp; fputs("ent ...