`
xpenxpen
  • 浏览: 704250 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

用spring-data-redis实现类似twitter的网站

阅读更多
1. spring-data-redis简介
封装了一下redis的客户端,使得使用起来更方便。
优点是把客户端连接放到一个连接池里,从而提高性能。还有就是可以不同的客户端之间实现切换,而不用改一行代码(Spring惯用的一个手法)。
本文写作时最新版是1.3,
目前支持下面4种java客户端,可以自由切换而不用改代码。


2. twitter简介
twitter如果没用过的话,可以理解成类似于国内的新浪微博。因为微博的访问量和使用人数极大,用传统的关系型数据库支撑不了,所以有了用redis这种非关系型数据库的架构设计。
本文我们将用spring-data-redis来实现一个类似twitter的网站。

3. 环境
本人亲测通过环境
jdk 1.6.0_45 64bit
gradle 1.7
tomcat 7.0.35
redis 2.8.11 win64
jedis 2.5.1
spring 3.2.9
spring-data-redis 1.3.0

4. 先动手操作
4.1 首先git clone以下项目
https://github.com/spring-projects/spring-data-keyvalue-examples/tree/master/retwisj

4.2 本人做了一些修改,一些3pp改成本文写作时最新的版本
build.gradle
compile "redis.clients:jedis:2.5.1"


gradle.properties
springVersion = 3.2.9.RELEASE
springRedisVersion = 1.3.0.RELEASE


4.3 编译
gradle build


4.4 将retwisj.war放入tomcat的webapp目录下,启动tomcat

4.5 访问http://localhost:8080/retwisj
花几分钟上去玩一下,熟悉一下功能。
好了,我们已经做好了一个微博网站了。玩好了我们简单分析一下代码实现。

5. 实现分析

5.1 表结构设计

5.1.1 用户(User)

用以前的关系型数据库设计是这样的
KeyUsernamePassword
1springrodinterface21
2costinlthis is fun


而用redis的则变成了这样
KeyTypeValue
uid:1hash{name: springrod, pass: interface21}
uid:2hash{name: costinl, pass: secret}


将用户的名字和密码作为一个hash存入
对应的redis原生命令是
HMSET user:1 name springrod pass interface21


uid是自增长的,可以用redis的INCR来实现,这是一个原子操作
INCR global:uid


KeyTypeValue
global:uidstring2


我们要保存username和uid的对应关系,比如一个user登录时,我们要得到他的uid。可以创建一个倒转的key来实现此功能。user:[name]:uid
还创建了一个users用来保存所有uid的list
KeyTypeValue
user:springrod:uidstring1
user:costinl:uidstring2
userslist{1, 2}


5.1.2 微博(Post)

同样的,用global:pid来记录自增长的post id
KeyTypeValue
global:pidstring2


将微博的内容、时间和作者作为一个hash存入
KeyTypeValue
pid:1hash{content: Hello World, time: 1301931414757, uid: 1}
pid:2hash{content: Working on some cool stuff, time: 1301931414897, uid: 1}
pid:3hash{content: Checking out RetwisJ, time: 1301931454897, uid: 2}


某个用户的所有微博
KeyTypeValue
uid:1:postslist{1, 2}
uid:2:postslist{3}


所有微博列表(Timeline)
KeyTypeValue
timelinelist{1, 2, 3}


5.1.3 关系(粉丝(Follower),关注(Following))

比如user2关注了user1,则user2是user1的粉丝,
user3也关注了user1,
则user1被user2,user3所关注

KeyTypeValue
uid:1:followersset{2,3}
uid:2:followingset{1}
uid:3:followingset{1}


新浪微博上姚晨的粉丝有7000万,光记录她一个人的粉丝就要7000万条记录。
如果用传统的关系型数据库实现,压力很大。

5.2 安全验证
我们不用session来跟踪用户,而用cookie。
每当用户登录后,为他生成一个随机数(令牌),发给该用户,让他作为cookie保存,这个cookie用来验证用户的身份。
同样的存储一个倒转的key,可以根据cookie来得到uid

KeyTypeValue
uid:2:authstring{fea5e81ac8ca77622bed1c2132a021f9}
auth:fea5e81ac8ca77622bed1c2132a021f9string{2}


5.3 包的结构
org.springframework.data.redis.sample.retwisj.webweb层
org.springframework.data.redis.sample.retwisj.redis持久层
org.springframework.data.redis.sample.retwisj领域层


5.4 使用redisTemplate
applicationContext-redis.xml
<beans>
  <context:property-placeholder location="classpath:redis.properties"/>

  <!-- Redis client 这里就是不改代码实现不同客户端切换的地方了,我们用jedis-->
  <bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
    p:host-name="${redis.host}" p:port="${redis.port}" p:password="${redis.pass}"/>

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

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

</beans>


5.5 web层
采用spring MVC和JSP

5.5.1 Controller层
RetwisController

5.5.2 CookieInterceptor
对于用户验证,采用cookie的方式,写了一个Spring MVC的拦截器
public class CookieInterceptor extends HandlerInterceptorAdapter


并在retwisj-servlet.xml里配置
<mvc:interceptors>
    <bean class="org.springframework.data.redis.samples.retwisj.web.CookieInterceptor" />
</mvc:interceptors>

执行效果就是在客户端保存了一个叫"retwisauth"的cookie,保存了用户的令牌。

5.5.3 i18

CookieLocaleResolver把语言作为cookie存在客户端
<bean id="localeResolver" class="org.springframework.web.servlet.i18n.CookieLocaleResolver"/>


执行效果就是在客户端保存了一个叫"org.springframework.web.servlet.i18n.CookieLocaleResolver.LOCALE"的cookie,保存了语言。

LocaleChangeInterceptor可以用来变更语言
<mvc:interceptors>
    <bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor" p:paramName="lang"/>
</mvc:interceptors>


这样就可以通过http://localhost:8080/retwisj/?lang=cn来变更语言

5.6 持久层
RetwisRepository

如下代码示例了如何用intersect来找出2个用户相同的粉丝

private RedisSet<String> following(String uid) {
    return new DefaultRedisSet<String>(KeyUtils.following(uid), template);
}

public List<String> commonFollowers(String uid, String targetUid) {
    RedisSet<String> tempSet = following(uid).intersectAndStore(following(targetUid),
    KeyUtils.commonFollowers(uid, targetUid));

    tempSet.expire(5, TimeUnit.SECONDS);

    return covertUidsToNames(tempSet.getKey());
}


如下代码示例了用RedisAtomicLong实现自增长的id,BoundHashOperations来存储用户的用户名和密码

public String addUser(String name, String password) {
    String uid = String.valueOf(userIdCounter.incrementAndGet());

    // save user as hash
    // uid -> user
    BoundHashOperations<String, String, String> userOps = template.boundHashOps(KeyUtils.uid(uid));
    userOps.put("name", name);
    userOps.put("pass", password);
    valueOps.set(KeyUtils.user(name), uid);

    users.addFirst(name);
    return addAuth(name);
}

分享到:
评论

相关推荐

    springboot学习思维笔记.xmind

    spring-boot-starter-redis spring-boot-starter-security spring-boot-starter-social-facebook spring-boot-starter-social-linkedin spring-boot-starter-social-twitter spring-...

    java品优购项目实战视频教程

    7.使用SpringDataRedis框架操作Redis、 8.使用Spring Data Solr框架操作solr 9.Solr新增动态域(Dynamic)知识点 10.掌握SPU和SKU的概念 11.搭建SpringBoot框架 12.实现阿里大于短信发送功能 13.使用CAS实现单点登录...

    基于Springboot+Thymeleaf实现的旅游景点酒店的预订网站+源代码+文档说明+数据库

    后台:SpringBoot、SpringDataJpa等 4.架构模式:半前后分离架构模式 5.模板引擎:thymeleaf 6.项目管理:Maven 7、JDK版本:1.8 8、额外功能:阿里云短信服务SMS、阿里云图片存储OSS、QQ邮箱验证服务 9、主要算法:...

    个人毕设项目-基于Springboot+Thymeleaf旅游景点酒店预订源码含sql数据库.zip

    基础能力强的可以在此基础上修改调整,以实现类似其他功能。 ## 旅游网是一个基于SpringBoot框架设计的一个毕业设计,主要类似于一个电商系统 ## 主要功能介绍 有用户登录注册,景点列表,相册墙,购买景点,评论,...

    基于SpringBoot+MySQL的旅游网站设计与实现.zip

    3.后台:SpringBoot、SpringDataJpa 等 4.架构模式:半前后分离架构模式 5.模板引擎:thymeleaf 6.项目管理:Maven 7、JDK 版本:1.8 8、额外功能:阿里云短信服务 SMS、阿里云图片存储 OSS、QQ 邮箱验证服务 9、...

    基于Springboot+Thymeleaf旅游景点酒店预订网站设计

    3.后台:SpringBoot、SpringDataJpa等 4.架构模式:半前后分离架构模式 5.模板引擎:thymeleaf 6.项目管理:Maven 7、JDK版本:1.8 8、额外功能:阿里云短信服务SMS、阿里云图片存储OSS、QQ邮箱验证服务 9、主要算法...

    基于Springboot+Thymeleaf旅游景点酒店预订网站

    3.后台:SpringBoot、SpringDataJpa等 4.架构模式:半前后分离架构模式 5.模板引擎:thymeleaf 6.项目管理:Maven 7、JDK版本:1.8 8、额外功能:阿里云短信服务SMS、阿里云图片存储OSS、QQ邮箱验证服务 9、主要算法...

    java开源包3

    WebSocket4J 是一个用 Java 实现的 WebSocket 协议的类库,可使用 Java 来构建交互式 Web 应用。WebSocket4J 并未实现客户端通讯协议,所以不能用它来连接 WebSocket 服务器。 Struts验证码插件 JCaptcha4Struts2 ...

    java开源包4

    WebSocket4J 是一个用 Java 实现的 WebSocket 协议的类库,可使用 Java 来构建交互式 Web 应用。WebSocket4J 并未实现客户端通讯协议,所以不能用它来连接 WebSocket 服务器。 Struts验证码插件 JCaptcha4Struts2 ...

    java开源包1

    WebSocket4J 是一个用 Java 实现的 WebSocket 协议的类库,可使用 Java 来构建交互式 Web 应用。WebSocket4J 并未实现客户端通讯协议,所以不能用它来连接 WebSocket 服务器。 Struts验证码插件 JCaptcha4Struts2 ...

    java开源包10

    WebSocket4J 是一个用 Java 实现的 WebSocket 协议的类库,可使用 Java 来构建交互式 Web 应用。WebSocket4J 并未实现客户端通讯协议,所以不能用它来连接 WebSocket 服务器。 Struts验证码插件 JCaptcha4Struts2 ...

    JAVA上百实例源码以及开源项目

    得到RSA密钥对,产生Signature对象,对用私钥对信息(info)签名,用指定算法产生签名对象,用私钥初始化签名对象,将待签名的数据传送给签名对象(须在初始化之后),用公钥验证签名结果,使用公钥初始化签名对象,用于...

    JAVA上百实例源码以及开源项目源代码

    得到RSA密钥对,产生Signature对象,对用私钥对信息(info)签名,用指定算法产生签名对象,用私钥初始化签名对象,将待签名的数据传送给签名对象(须在初始化之后),用公钥验证签名结果,使用公钥初始化签名对象,用于...

    java开源包8

    WebSocket4J 是一个用 Java 实现的 WebSocket 协议的类库,可使用 Java 来构建交互式 Web 应用。WebSocket4J 并未实现客户端通讯协议,所以不能用它来连接 WebSocket 服务器。 Struts验证码插件 JCaptcha4Struts2 ...

    java开源包11

    WebSocket4J 是一个用 Java 实现的 WebSocket 协议的类库,可使用 Java 来构建交互式 Web 应用。WebSocket4J 并未实现客户端通讯协议,所以不能用它来连接 WebSocket 服务器。 Struts验证码插件 JCaptcha4Struts2 ...

    java开源包2

    WebSocket4J 是一个用 Java 实现的 WebSocket 协议的类库,可使用 Java 来构建交互式 Web 应用。WebSocket4J 并未实现客户端通讯协议,所以不能用它来连接 WebSocket 服务器。 Struts验证码插件 JCaptcha4Struts2 ...

    java开源包6

    WebSocket4J 是一个用 Java 实现的 WebSocket 协议的类库,可使用 Java 来构建交互式 Web 应用。WebSocket4J 并未实现客户端通讯协议,所以不能用它来连接 WebSocket 服务器。 Struts验证码插件 JCaptcha4Struts2 ...

    java开源包5

    WebSocket4J 是一个用 Java 实现的 WebSocket 协议的类库,可使用 Java 来构建交互式 Web 应用。WebSocket4J 并未实现客户端通讯协议,所以不能用它来连接 WebSocket 服务器。 Struts验证码插件 JCaptcha4Struts2 ...

    java开源包7

    WebSocket4J 是一个用 Java 实现的 WebSocket 协议的类库,可使用 Java 来构建交互式 Web 应用。WebSocket4J 并未实现客户端通讯协议,所以不能用它来连接 WebSocket 服务器。 Struts验证码插件 JCaptcha4Struts2 ...

Global site tag (gtag.js) - Google Analytics