Redis、Spring Data 和 Cloud Foundry 入门

工程 | Costin Leau | 2011年4月27日 | ...

NoSQL 解决方案受欢迎的原因之一是(尤其是在高负载下)的性能。由于其数据模型,键值存储在这一领域处于领先地位,提供了轻量级但灵活的数据处理方式。在本篇文章中,我将通过 Spring Data 的一个示例 (RetwisJ) 快速展示如何使用 Spring (Spring Redis) 来处理键值存储 (Redis),并将应用程序部署到 (通过 Cloud Foundry) 上与世界分享。为了有所改变,我甚至还将使用 Windows 作为部署平台。

Redis

键值存储中一个流行的 选择Redis,这是一个开源的、极快的数据库,用 ANSI C 编写,服务器端仅重约 200 KB(是的,是 **千** 字节),整个软件包(包括命令行客户端和一些管理工具)约为 400 KB,并且几乎可以在所有主流平台上使用,这也是它成为示例选择的原因。请注意,除非您想在本地运行示例,否则不需要 Redis 实例。如果需要,对于 Windows 用户(例如作者),我(及时的)使用(并推荐)这个预打包版本,提供 32 位和 64 位版本。

Spring 和 NoSQL

如果您在 Java 环境中使用 NoSQL,不妨看看 Spring Data:它本身不是一个项目,而是一个项目集合,涵盖了各种新的数据访问技术,如非关系型数据库(如 Redis 或 MongoDB)、MapReduce 框架(例如 Hadoop)以及面向 Java 应用程序的云数据服务。Spring Data 秉承了 **经典的** Spring 理念,通过消除 API 噪音、样板代码和资源管理,并提供一致的编程模型,从而提高了开发者的生产力。它建立在现有的 Spring 功能和项目(如控制反转、生命周期管理、类型转换、可移植数据访问异常、缓存等)之上,因此您可以轻松地将其添加到应用程序中。当然,就像其他 Spring 项目一样,它是开源的,并根据 Apache 许可证提供。

Spring Data Redis

对于 Redis,Spring Data 通过 Spring Data Redis 或简单地称为 Spring Redis 项目提供专用支持。它提供了低级和高级功能,从可移植的 Redis 客户端抽象(允许通过一行配置即可更换不同的 Redis 客户端,如 Jedis、JRedis 或 RJC)到 Redis 支持的原子集合或计数器或发布/订阅支持。该项目的 参考 文档详细介绍了这些主题。

RetwisJ,YATC - 又一个 Twitter 克隆

RetwisJ 的源代码,包括本博文中的代码,可以在 Spring Data Key Value 的 示例项目 中下载。此外,文档 在此处 提供。

RetwisJ 可以看作是 Redis 的 Retwis 示例的 Java 移植版本:一个简单的 Twitter 克隆,演示了如何用 Redis 灵活的数据模型(例如集合 交集)来替代传统关系型数据库中昂贵的 JOIN 操作。

从面向表的思维方式迁移到键值关联可能看起来很困难,但事实并非如此:与其在一个键下存储多个值,不如将每个值存储在“相似的键”下;事实上,关系本身也可以这样存储。正如 文档 所解释的那样,与其创建一个用户表(包含一个用户名字段、一个密码字段等等),不如直接使用 Redis hash(或 map)来存储数据,并且为了存储条目之间的关系,可以添加一个单独的、反向的或查找键,而不是创建索引。因此,以下表格结构(用户)可以部署为以下键值对:

用户名密码
1springrodinterface21
2costinlthis is fun
  变成  
类型
uid:1hash{name: springrod, pass: interface21}
uid:2hash{name: costinl, pass: secret}

同样,关注者和被关注者(或目标)之间的关联表可以通过 Redis Set 来映射。因此,与其执行表连接,不如简单地进行集合交集运算。Redis 丰富的模型(Set、Z-Set(或有序集合)、List 和 Hash)与 Spring Redis 中的 Java 集合相映射,Spring Redis 提供了相应的java.util在 Redis 之上的实现。这意味着可以使用熟悉的接口来遍历、查找或修改列表和集合,而无需手动发出任何 Redis 命令。

也就是说

private RedisSet<String> following(String uid) {
   return new DefaultRedisSet<String>(KeyUtils.following(uid), template);
}
      
public Collection<String> commonFollowers(String uid, String targetUid) {
   Set<String> followers = following(uid).
       intersectAndStore(following(targetUid),
       KeyUtils.commonFollowers(uid, targetUid));
   ...
}

对于通用数据访问,核心的 Spring Redis 是RedisTemplate它支持从简单的、单行的丰富对象操作、序列化(无论是字节数组、XML 还是基于 Jackson 的)或消息发布,到高级的查询能力和数据获取(例如通过 Redis SORT/GET 模式避免臭名昭著的 N+1 问题)。

// adding entries into a hash
BoundHashOperations<String, String, String> userOps = template.boundHashOps(KeyUtils.uid(uid));
userOps.put("name", name);
userOps.put("pass", password);
valueOps.set(KeyUtils.user(name), uid);

有关数据模型和示例的更深入解释,请参阅 RetwisJ 文档

连接到 Redis

Java 用户在连接到 Redis 时遇到的一个常见问题是使用哪个 客户端(或驱动程序)。Spring Redis 以一致的方式支持三种不同的库(JedisJRedisRJC),因此可以轻松地在它们之间切换,而无需重写任何代码。让我们以 Jedis 为例,看看应用程序的配置是什么样的。

<beans>
  <context:property-placeholder location="classpath:redis.properties"/>

  <!-- Redis client -->
  <bean id="connectionFactory" class="org.springframework.data.keyvalue.redis.connection.jedis.JedisConnectionFactory"
		p:host-name="${redis.hostname}" p:port="${redis.port}" p:password="${redis.password}"/>

	<bean id="redisTemplate" class="org.springframework.data.keyvalue.redis.core.StringRedisTemplate" 
		p:connection-factory-ref="connectionFactory"/>

	<context:annotation-config />
	<context:component-scan base-package="org.springframework.data.redis.samples"/>

</beans>

非常直接——我们声明驱动程序和 Redis 属性(在运行时通过属性占位符从redis.properties)进行替换,启用注解配置,并扫描类路径中的 bean。

从部署角度来看,RetwisJ 只是一个 Web 应用程序,一个 WAR 文件,可以部署在任何(Servlet 2.5)Web 容器中,如 Tomcat。它由一个简单的 Spring@MVC控制器、一个仓库类和两个领域对象Post还是User组成。为了遵循 Retwis 示例,即使是安全性也将通过 Redis 处理,而不是通过容器的HttpSession——这不仅展示了键值存储的另一个用例,还提高了可伸缩性,因为 Redis(以及用户数据)是开箱即用的分布式。

要构建它,只需在根文件夹中输入

./gradlew build

然后部署生成的 war 文件(build/libs/retwisj.war)到您选择的 Web 容器中来运行它。

将 RetwisJ 部署到 Cloud Foundry

Cloud Foundry 就绪的 RetwisJ 示例可在专用的示例 存储库 中找到。

将上面的 WAR 文件部署到 Cloud Foundry 非常直接——您只需要一个帐户(您可以 在此处 免费注册)。一旦拥有了帐户,您就可以通过 STS(如之前 文章 中详细介绍)或命令行(vmc)来部署您的应用程序,我将在本文中使用后者。

由于我们正在使用 Redis,我们需要将本地实例属性替换为适合 Cloud Foundry 的属性,这些属性作为环境变量公开。如这些 文档 中所述,Spring 通过cloud命名空间提供了专门的支持。

我们可以利用这一点,因此我们不是从本地文件读取 Redis 属性,而是可以从环境变量中获取这些属性。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
		xmlns:p="http://www.springframework.org/schema/p"
		xmlns:context="http://www.springframework.org/schema/context"
		xmlns:cloud="http://schema.cloudfoundry.org/spring"
		xsi:schemaLocation="
			http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
			http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
      http://schema.cloudfoundry.org/spring http://schema.cloudfoundry.org/spring/cloudfoundry-spring.xsd">

  	<cloud:service-properties id="cfoundryEnv" />
  	<context:property-placeholder properties-ref="cfoundryEnv"/>
	  
    <bean id="connectionFactory" class="org.springframework.data.keyvalue.redis.connection.jedis.JedisConnectionFactory"
      p:host-name="${redis.hostname}" p:port="${redis.port}" p:password="${redis.password}"/>

属性名称不必更改——我们可以命名(在本例中为redis)绑定到应用程序的 Redis 实例,并使用它来最小化本地环境和云之间的更改。

请注意,这只是众多选项中的一种:您可以使用 Spring 3.1 配置文件 自动进行切换,使用 cloud 命名空间自动为您创建一个RedisConnectionFactory或自动将其连接到您的应用程序。有关可用功能的更多信息,请参阅此 部分

现在让我们将我们的 Twitter 克隆部署到云中!

对于像我这样的命令行爱好者,Cloud Foundry 提供了vmc实用程序,它允许您与 Cloud Foundry 实例进行交互。它是用 Ruby 编写的,所以您需要安装 Ruby 和 Ruby Gem——请参阅适用于您操作系统的软件包的 下载 页面。对于 Windows,优秀的 RubyInstaller(无论是安装程序还是 zip 形式)都可以很好地解决这个问题,它提供了本地集成(如果您不想使用 Cygwin 等)。如果gem命令不可用,请从官方 网站 下载,解压它即可。

有关可用命令的更多信息,请参阅入门 指南

q:\>gem install vmc
Successfully installed vmc-0.3.10
1 gem installed
Installing ri documentation for vmc-0.3.10...
Installing RDoc documentation for vmc-0.3.10...

登录到我们的帐户

Q:\>vmc target api.cloudfoundry.com
Succesfully targeted to [http://api.cloudfoundry.com]

Q:\>vmc login
Email: <signup email>
Password: **************
Successfully logged into [http://api.cloudfoundry.com]

最后一步就是上传我们的 WAR 文件。


Q:\>dir /B
retwisj.war

Q:\>vmc push
Would you like to deploy from the current directory? [Yn]: y
Application Name: my-retwisj
Application Deployed URL: 'my-retwisj.cloudfoundry.com'?
Detected a Java SpringSource Spring Application, is this correct? [Yn]: y
Memory Reservation [Default:512M](64M, 128M, 256M, 512M or 1G)
Creating Application: OK
Would you like to bind any services to 'my-retwisj'? [yN]: y
The following system services are available::
1. mongodb
2. mysql
3. rabbitmq
4. redis
Please select one you wish to provision: 4
Specify the name of the service [redis-866fb]: redis
Creating Service: OK
Binding Service: OK
Uploading Application:
  Checking for available resources: OK
  Processing resources: OK
  Packing application: OK
  Uploading (32K): OK
Push Status: OK

Staging Application: OK

Starting Application: OK

Q:\>vmc apps

+-------------+----+---------+------------------------------+-------------+
| Application | #  | Health  | URLS                         | Services    |
+-------------+----+---------+------------------------------+-------------+
| my-retwisj  | 1  | RUNNING | my-retwisj.cloudfoundry.com  | redis       |
+-------------+----+---------+------------------------------+-------------+

上述过程即使在连接缓慢的情况下也不应超过 1 分钟(这篇博客 文章 深入介绍了在push操作期间发生的情况)。您可能已经注意到只上传了 32K;这不是错误,vmc能够智能地确定它已经知道的文件(例如已部署的文件)以及实际发生变化的文件。

就是这样!——只需将您的浏览器指向上面的 URL,即可享受您的 RetwisJ 示例。'官方'的实时实例可在 http://retwisj.cloudfoundry.com/ 访问。

总结

本文涵盖了相当多的内容:Redis、Spring Data 和 Cloud Foundry 部署。我希望这能说明入门的容易程度以及这种组合的强大功能,无论是在本地环境还是在云中。而这仅仅是开始!预计 Spring Redis(即将接近 RC 状态)以及 Cloud Foundry(无论是有更多服务还是更好的工具)都会添加更多功能。

尝试一下,让我们知道您的想法和需求!

获取 Spring 新闻通讯

通过 Spring 新闻通讯保持联系

订阅

领先一步

VMware 提供培训和认证,助您加速进步。

了解更多

获得支持

Tanzu Spring 提供 OpenJDK™、Spring 和 Apache Tomcat® 的支持和二进制文件,只需一份简单的订阅。

了解更多

即将举行的活动

查看 Spring 社区所有即将举行的活动。

查看所有