领先一步
VMware 提供培训和认证,助您加速进步。
了解更多NoSQL 解决方案受欢迎的原因之一是(尤其是在高负载下)的性能。由于其数据模型,键值存储在这一领域处于领先地位,提供了轻量级但灵活的数据处理方式。在本篇文章中,我将通过 Spring Data 的一个示例 (RetwisJ) 快速展示如何使用 Spring (Spring Redis) 来处理键值存储 (Redis),并将应用程序部署到 云 (通过 Cloud Foundry) 上与世界分享。为了有所改变,我甚至还将使用 Windows 作为部署平台。
RetwisJ 的源代码,包括本博文中的代码,可以在 Spring Data Key Value 的 示例项目 中下载。此外,文档 在此处 提供。
RetwisJ 可以看作是 Redis 的 Retwis 示例的 Java 移植版本:一个简单的 Twitter 克隆,演示了如何用 Redis 灵活的数据模型(例如集合 交集)来替代传统关系型数据库中昂贵的 JOIN 操作。
从面向表的思维方式迁移到键值关联可能看起来很困难,但事实并非如此:与其在一个键下存储多个值,不如将每个值存储在“相似的键”下;事实上,关系本身也可以这样存储。正如 文档 所解释的那样,与其创建一个用户表(包含一个用户名字段、一个密码字段等等),不如直接使用 Redis hash(或 map)来存储数据,并且为了存储条目之间的关系,可以添加一个单独的、反向的或查找键,而不是创建索引。因此,以下表格结构(用户)可以部署为以下键值对:
键 用户名 密码
1 springrod interface21
2 costinl this is fun
变成
键 类型 值
uid:1 hash {name: springrod, pass: interface21}
uid:2 hash {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 文档。
Java 用户在连接到 Redis 时遇到的一个常见问题是使用哪个 客户端(或驱动程序)。Spring Redis 以一致的方式支持三种不同的库(Jedis、JRedis 和 RJC),因此可以轻松地在它们之间切换,而无需重写任何代码。让我们以 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 容器中来运行它。
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/ 访问。
尝试一下,让我们知道您的想法和需求!