使用 Redis 构建简单的 URL 缩短服务






4.57/5 (4投票s)
在本文中,我将向您展示如何使用 Redis 和 ASP.NET MVC 构建一个简单的 URL 缩短服务。
在阅读本文之前,我建议您先下载源代码。
什么是 Redis
与 memcached 类似,Redis 是一种内存数据库。除此之外,Redis 还允许您将数据保存到硬盘上,这使得 Redis 不仅仅是一个缓存,还是一个 NoSQL 数据库。
构建 Web 应用程序
首先,在 Visual Studio 中创建一个 ASP.NET MVC 项目,不使用身份验证。
然后,在 Models 文件夹中添加一个类来存储 URL 数据
public class MicroUrlItem
{
[Display(Name = "Shorten URL")]
public string ShortenUrl { get; set; }
[Required]
[Display(Name = "Origin URL")]
[Url]
public string OrignUrl { get; set; }
[Range(1, double.MaxValue)]
[Display(Name = "Expire in Days")]
public int ExpireInDays { get; set; }
[Display(Name = "Expire Mode")]
public ExpireMode ExpireMode { get; set; }
}
ExpireMode 是一个自定义枚举,因此我们需要声明它。
public enum ExpireMode
{
[Display(Name = "By Created")]
ByCreated = 0,
[Display(Name = "By Last Accessed")]
ByLastAccessed = 1,
[Display(Name = "Never")]
Never = 2
}
之后,添加一个主页
@model MicroUrl.Models.MicroUrlItem
@{
ViewBag.Title = "Home Page";
}
<h3>Get you micro URL here</h3>
<div class="row">
@using (Html.BeginForm("Index", "Home", FormMethod.Post, new { role = "form", @class = "col-lg-6" }))
{
<div class="form-group">
@Html.LabelFor(m => m.OrignUrl)
@Html.TextBoxFor(m => m.OrignUrl, new { @class = "form-control" })
@Html.ValidationMessageFor(m => m.OrignUrl, "", new { @class = "text-danger" })
</div>
<div class="form-group">
@Html.LabelFor(m => m.ShortenUrl)
@Html.TextBoxFor(m => m.ShortenUrl, new { @class = "form-control", placeHolder = "Keep it empty to generate automatically" })
@Html.ValidationMessageFor(m => m.ShortenUrl, "", new { @class = "text-danger" })
</div>
<div class="form-group">
@Html.LabelFor(m => m.ExpireMode)
@Html.EnumDropDownListFor(m => m.ExpireMode, new { @class = "form-control" })
@Html.ValidationMessageFor(m => m.ExpireMode, "", new { @class = "text-danger" })
</div>
<div class="form-group">
@Html.LabelFor(m => m.ExpireInDays)
@Html.TextBoxFor(m => m.ExpireInDays, new { @class = "form-control" })
@Html.ValidationMessageFor(m => m.ExpireInDays, "", new { @class = "text-danger" })
</div>
<button type="submit" class="btn btn-default">Create</button>
}
</div>
它看起来像这样
此代码段中一个有趣的事情是 HtmlHelper 中的 EnumDropDownListFor 方法,该方法直到 ASP.NET MVC 5.2 才可用。
在早期版本的 ASP.NET MVC 中,如果没有此方法,我们必须手动创建下拉列表项,这是一项脏活。
但现在我们可以使用此方法从枚举生成项目,并使用 Display 属性设置其显示名称。
然后我们需要一个页面来告诉用户操作已在 Success.cshtml 中成功,这很简单。
@model MicroUrl.Models.MicroUrlItem
@{
ViewBag.Title = "Success";
}
<h2>Success</h2>
<h3>
@{
var url = string.Format("http://{0}:{1}/{2}", Request.Url.Host, Request.Url.Port, Model.ShortenUrl);
}
Your Micro URL is <a href="@url">@url</a>
</h3>
将对象保存到 Redis
在完成上述准备工作后,我们现在可以开始编写代码将数据存储在 Redis 中。
首先需要一个名为 ServiceStack.Redis 的 Nuget 包。我们可以在 Package Manager 中搜索 redis,或者使用以下命令在控制台中安装
PM> Install-Package ServiceStack.Redis
顺便说一句,如果您需要引用一个具有强名称的已签名程序集,则可以安装 ServiceStack.Redis.Signed。
然后我们可以使用 using 语句创建一个 redis 客户端,并获取一个类型化的客户端来处理 MicroUrlItem。
using (IRedisClient client = new RedisClient())
{
var typedClient = client.As<MicroUrlItem>();
//...
}
在将对象保存在 Redis 中之前,我们需要使用 ServiceStack.DataAnnotations.PrimaryKey 属性将 ShortenUrl 属性标记为主键,因此最终 MicroUrlItem 中的 ShortenUrl 属性应为
public class MicroUrlItem
{
[ServiceStack.DataAnnotations.PrimaryKey]
[Display(Name = "Shorten URL")]
public string ShortenUrl { get; set; }
//other properties
//...
}
我们需要做的另一件事是在未指定 ShortenUrl 时生成一个随机 URL。
if (string.IsNullOrWhiteSpace(model.ShortenUrl))
{
string url;
do
{
url = GetRandomUrl(6);
} while (typedClient.GetById(url) != null);
model.ShortenUrl = url;
}
这是我生成随机 URL 的方法
private static string randomList = "0123456789abcdefghijklmnopqrstuwxyz";
private static string GetRandomUrl(int length)
{
var sb = new StringBuilder(length);
var random = new Random();
for (int i = 0; i < length; i++)
{
var index = random.Next(0, randomList.Length);
sb.Append(randomList[index]);
}
return sb.ToString();
}
现在模型已准备好保存到 Redis
typedClient.Store(model);
最后,我们需要告诉 Redis,如果指定了过期时间,则对象何时过期。
if (model.ExpireMode != ExpireMode.Never)
typedClient.ExpireIn(model.ShortenUrl, TimeSpan.FromDays(model.ExpireInDays));
从 Redis 获取对象
[Route("{shortenUrl}")]
public ActionResult Index(string shortenUrl)
{
using (IRedisClient client = new RedisClient())
{
var typedClient = client.As<MicroUrlItem>();
var microUrlItem = typedClient.GetById(shortenUrl);
if (microUrlItem != null)
{
//renew the record
if (microUrlItem.ExpireMode == ExpireMode.ByLastAccessed)
typedClient.ExpireIn(microUrlItem.ShortenUrl, TimeSpan.FromDays(microUrlItem.ExpireInDays));
return Redirect(microUrlItem.OrignUrl);
}
}
return HttpNotFound();
}
现在我们可以用同样的方式创建一个类型化的客户端,如果找到匹配的记录,则返回带有 HTTP 302 的响应。当访问缩短的 URL 时,如果其 ExpireMode 属性设置为 ByLastAccessed,我们应该 renew 它。
另一件重要的事情是使 Route 属性起作用,只需在应用程序启动时将 AttributeRoutes 映射到 ASP.NET MVC 路由系统。
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
//map the AttributeRoutes
routes.MapMvcAttributeRoutes();
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
运行应用程序
在运行此应用程序之前,我们需要启动 Redis,要获取 Redis,您可以转到 https://redis.ac.cn/download 下载它。
对于 Windows,启动命令提示符并转到 Redis 文件夹,然后运行
redis-server.exe --maxheap 1gb
我们还可以启动一个命令行客户端来启动一个监视器
然后我们可以在 Visual Studio 中启动网站,并创建一个缩短的 URL。
这是自定义 URL
这是由服务生成的 URL
在我们得到微型 URL 后,我们可以在监视器中看到 Redis 中发生的情况。
感谢阅读!