领先一步
VMware 提供培训和认证,助您快速进步。
了解更多NoSQL 解决方案流行的驱动因素之一是性能(尤其是在高负载下)。由于其数据模型,键值存储位居前列,提供了轻量级而灵活的数据处理方式。在这篇文章中,我将快速展示如何使用 Spring (Spring Redis) 通过 Spring Data 的一个示例 (RetwisJ) 与键值存储 (Redis) 协作,并将应用程序部署到云(通过 Cloud Foundry)中与世界分享。我甚至更进一步,尝试使用 Windows 作为部署平台。
RetwisJ 源代码,包括本博客中的代码,可以在 Spring Data Key Value 的示例项目中下载。此外,文档可以在此处获取
RetwisJ 可以看作是 Redis Retwis 示例的 Java 移植:一个简单的 Twitter 克隆,演示了如何用 Redis 灵活的数据模型(例如集合交集)替代传统关系型数据库中开销高昂的联接。
从表格思维模式迁移到键值关联可能看起来很难,但事实并非如此:与其将多个值存储在一个键下,不如将每个值存储在“类似的键”下;事实上,关系本身也可以这样存储。正如文档中所述,与其为用户创建一个表(包含用户名、密码等列),不如通过 Redis 哈希(或 map)存储各项,并为条目之间的关系添加一个单独的、反向的或查找键,而不是创建索引。因此,以下表格结构(用户)可以部署为以下键值对:
键 用户名 密码
1 springrod interface21
2 costinl this is fun
变为
键 类型 值
uid:1 hash {name: springrod, pass: interface21}
uid:2 hash {name: costinl, pass: secret}
类似地,关注者与被关注者(或目标)之间的关联表可以通过 Redis Sets 进行映射。因此,与其执行表联接,不如简单地进行集合交集。Redis 丰富的数据模型(Sets、Z-Sets(或有序集合)、Lists 和 Hashes)通过 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)在运行时替换),我们启用注解配置并扫描 classpath 以查找 bean。
从部署的角度来看,RetwisJ 只是一个 Web 应用程序,一个 WAR 包,可以部署到任何 (Servlet 2.5) Web 容器中,例如 Tomcat。它由一个简单的 Spring@MVC控制器、一个Repository类和两个领域对象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 的profiles 自动进行切换,使用 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/ 找到
尝试一下吧,并告诉我们您的想法和需求!