1. 今日大纲

  1. 学习Redis
  2. 使用Redis完成项目中缓存需求
  3. 实现商品详情页功能
    1. 缓存的需求

大广告位数据无需每次查询后台系统的接口,可以在前台系统添加缓存,提高访问首页的速度。

商品类目的数据也可以缓存起来。

实现:

使用Redis实现缓存。

目前缓存的主流技术:

  1. Redis
  2. Memcached

二者谁的性能更高?

  1. 单纯从缓存命中的角度来说,是Memcached要高,Redis和Memcache的差距不大
  2. 但是,Redis提供的功能更加的强大

二者的区别是什么?

  1. Memcache是多线程
  2. Redis是单线程
    1. Redis

      1. NoSQL

  1. 主流的NoSQL产品

  1. Redis简介

Redis官网: http://redis.io/

  1. 历史与发展

  1. Redis的特性

  1. Redis版本说明

  1. 下载Redis

Linux版本 2.8.11 :

http://download.redis.io/releases/redis-2.8.11.tar.gz

Windows(64位)版本 2.8.9 :

https://github.com/MSOpenTech/redis/blob/2.8/bin/release/redis-2.8.9.zip?raw=true

Windows(32位)版本 2.6 :

https://github.com/MSOpenTech/redis/blob/2.6/bin/release/redisbin.zip?raw=true

  1. Redis的安装

    1. 安装文件

  1. 安装方式一

双机打开redis-server.exe即可:

测试:

  1. 安装方式二(安装到系统服务)

先删除原有的系统服务:

安装服务:

  1. 32位操作系统安装

只能通过双击打开redis-server.exe启动,不能安装到系统服务。

  1. 注意事项

由于文件系统非NTFS,导致Redis启动失败:

限制Redis的最大内存:

  1. Redis-cli使用

    1. redis-cli的使用之发送命令

  1. redis-cli的使用之命令返回值

  1. Redis的多数据库

FLUSHALL -- 清空所有数据库的所有数据

FLUSHDB -- 清空当前所在数据库的数据

  1. 配置数据库数量

  1. Redis的基本命令

    1. KEYS

  1. EXISTS

  1. DEL

  1. TYPE

  1. HELP

HELP 空格 tab键

  1. Redis的字符串数据类型

    1. 字符串类型

  1. GET、SET

  1. INCR

  1. INCRBY

  1. DECR、DECRBY

  1. APPEND

  1. STRLEN

  1. MSET、MGET

  1. Redis的Hash数据结构

    1. 数据结构

  1. 基本操作

  1. 判断是否存在和选择性插入

  1. Hash的自增长

  1. 只获取字段名或字段值

  1. 获取字段数量

  1. Redis之生存时间

    1. 设置生存时间

TTL返回值:

大于0的数字:剩余生存时间,单位为秒

-1 : 没有生存时间,永久存储

-2 : 数据已经被删除

  1. 清除生存时间

  1. 设置单位为毫秒

  1. 客户端

    1. 支持的语言

  1. Jedis

官网:

  1. Jedis的使用

    1. 导入itcast-redis

  1. 导入依赖

  1. 简单示例

  1. 连接池使用

  1. 分片式集群

存在的问题:无法动态增加减少服务节点。

  1. 分片式集群的使用

public
class ShardedJedisPoolDemo {

public
static
void main(String[] args) {

// 构建连接池配置信息

JedisPoolConfig poolConfig = new JedisPoolConfig();

// 设置最大连接数

poolConfig.setMaxTotal(50);

// 定义集群信息

List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>();

shards.add(new JedisShardInfo("127.0.0.1", 6379));

shards.add(new JedisShardInfo("192.168.29.112", 6379));

// 定义集群连接池

ShardedJedisPool shardedJedisPool = new ShardedJedisPool(poolConfig, shards);

ShardedJedis shardedJedis = null;

try {

// 从连接池中获取到jedis分片对象

shardedJedis = shardedJedisPool.getResource();

// for (int i = 0; i < 100; i++) {

// shardedJedis.set("key_" + i, "value_" + i);

// }

System.out.println(shardedJedis.get("key_49"));

System.out.println(shardedJedis.get("key_7"));

} catch (Exception e) {

e.printStackTrace();

} finally {

if (null != shardedJedis) {

// 关闭,检测连接是否有效,有效则放回到连接池中,无效则重置状态

shardedJedis.close();

}

}

// 关闭连接池

shardedJedisPool.close();

}

}

  1. 将Jedis集成到项目中

    1. 添加缓存前的测试

  1. 后台系统中添加缓存

    1. 在Service中添加依赖

  1. Spring和Jedis的整合

  1. 封装RedisService

package com.taotao.manage.service;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

import redis.clients.jedis.ShardedJedis;

import redis.clients.jedis.ShardedJedisPool;

@Service

public
class RedisService {

@Autowired

private ShardedJedisPool shardedJedisPool;

/**

* 执行set操作

*

* @param key

* @param value

* @return

*/

public String set(String key, String value) {

ShardedJedis shardedJedis = null;

try {

// 从连接池中获取到jedis分片对象

shardedJedis = shardedJedisPool.getResource();

return
shardedJedis.set(key, value);

} finally {

if (null != shardedJedis) {

// 关闭,检测连接是否有效,有效则放回到连接池中,无效则重置状态

shardedJedis.close();

}

}

}

/**

* 执行get操作

*

* @param key

* @return

*/

public String get(String key) {

ShardedJedis shardedJedis = null;

try {

// 从连接池中获取到jedis分片对象

shardedJedis = shardedJedisPool.getResource();

return
shardedJedis.get(key);

} finally {

if (null != shardedJedis) {

// 关闭,检测连接是否有效,有效则放回到连接池中,无效则重置状态

shardedJedis.close();

}

}

}

}

  1. 优化RedisService

定义接口:

RedisService的实现:

package com.taotao.manage.service;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

import redis.clients.jedis.ShardedJedis;

import redis.clients.jedis.ShardedJedisPool;

@Service

public
class RedisService {

@Autowired

private ShardedJedisPool shardedJedisPool;

private <T> T execute(Function<T, ShardedJedis> fun) {

ShardedJedis shardedJedis = null;

try {

// 从连接池中获取到jedis分片对象

shardedJedis = shardedJedisPool.getResource();

return
fun.callback(shardedJedis);

} finally {

if (null != shardedJedis) {

// 关闭,检测连接是否有效,有效则放回到连接池中,无效则重置状态

shardedJedis.close();

}

}

}

/**

* 执行set操作

*

* @param key

* @param value

* @return

*/

public String set(final String key, final String value) {

return
this.execute(new Function<String, ShardedJedis>() {

@Override

public String callback(ShardedJedis e) {

return
e.set(key, value);

}

});

}

/**

* 执行get操作

*

* @param key

* @return

*/

public String get(final String key) {

return
this.execute(new Function<String, ShardedJedis>() {

@Override

public String callback(ShardedJedis e) {

return
e.get(key);

}

});

}

/**

* 执行删除操作

*

* @param key

* @return

*/

public Long del(final String key) {

return
this.execute(new Function<Long, ShardedJedis>() {

@Override

public Long callback(ShardedJedis e) {

return
e.del(key);

}

});

}

/**

* 设置生存时间,单位为:秒

*

* @param key

* @param seconds

* @return

*/

public Long expire(final String key, final Integer seconds) {

return
this.execute(new Function<Long, ShardedJedis>() {

@Override

public Long callback(ShardedJedis e) {

return
e.expire(key, seconds);

}

});

}

/**

* 执行set操作并且设置生存时间,单位为:秒

*

* @param key

* @param value

* @return

*/

public String set(final String key, final String value, final Integer seconds) {

return
this.execute(new Function<String, ShardedJedis>() {

@Override

public String callback(ShardedJedis e) {

String str = e.set(key, value);

e.expire(key, seconds);

return
str;

}

});

}

}

  1. 实现缓存逻辑

  1. 先从缓存中命中,命中则返回
  2. 将结果写入到Redis中
  1. 测试

  1. 原则

原则:缓存逻辑不能影响原有的业务逻辑执行。

  1. 优化之后的缓存实现

  1. 商品详情页

    1. 进入商品详情页地址

http://www.taotao.com/item/{itemId}.html

  1. 商品基本数据显示

    1. Controller

  1. Item对象

  1. Service

  1. 后台系统提供接口服务

  1. Item.jsp中使用模型数据

显示商品价格:

<fmt:formatNumber groupingUsed="false" maxFractionDigits="2" minFractionDigits="2" value="${item.price / 100 }"/>

  1. 测试

  1. 显示商品描述数据

    1. Controller

  1. Service

  1. 后台系统中开放接口服务

  1. Item.jsp中显示数据

  1. 效果

  1. 显示规格参数数据

    1. Controller

  1. Service

  1. Item.jsp

  1. 效果

  1. 字符串拼接面试题

  1. 商品详情页添加缓存

    1. 为什么要添加缓存?

加快显示商品 详情页的速度。

  1. 在哪里添加缓存?

前台系统? 还是 后台系统? --- 都加。

每个团队都应该为自己的系统功能负责任,保证其性能。

  1. 前台系统添加缓存

    1. 导入依赖

  1. 导入Spring和Jedis的整合文件

  1. 将RedisService和Function接口移动至taotao-common

  1. Service中添加缓存逻辑

private
static
final
String
REDIS_KEY = "TAOTAO_WEB_ITEM_DETAIL_";

private
static
final Integer REDIS_TIME = 60 * 60 * 24;

public Item queryItemById(Long itemId) {

// 从缓存中命中

String key = REDIS_KEY + itemId;

try {

String cacheData = this.redisService.get(key);

if (StringUtils.isNotEmpty(cacheData)) {

return
MAPPER.readValue(cacheData, Item.class);

}

} catch (Exception e1) {

e1.printStackTrace();

}

try {

String url = TAOTAO_MANAGE_URL + "/rest/item/" + itemId;

String jsonData = this.apiService.doGet(url);

if (StringUtils.isEmpty(jsonData)) {

return
null;

}

try {

// 将数据写入到缓存中

this.redisService.set(key, jsonData, REDIS_TIME);

} catch (Exception e) {

e.printStackTrace();

}

return
MAPPER.readValue(jsonData, Item.class);

} catch (Exception e) {

e.printStackTrace();

}

return
null;

}

  1. 商品数据同步问题

    1. 问题

后台系统中将商品修改,前台系统没有进行数据的同步,导致前端系统不能够实时显示最新的数据。

  1. 解决

后台系统中商品修改后向其他系统发送通知,其他系统做出对应的处理即可。

  1. 怎么通知?

  1. 在前台系统中开发一个接口
  2. 在后台系统中调用该接口
  1. ApiService移动至taotao-common

  1. 实现数据同步存在的问题

通知的实现,代码的耦合度太高了。

怎么解决? -- 消息队列。

淘淘商城_day05_课堂笔记的更多相关文章

  1. 淘淘商城_day11_课堂笔记

    今日大纲 发布前的准备 实施发布 一部分是由我来发布 一部分是由你们来发布 讲解分布式部署架构 测试 功能测试 压力测试 项目实战的准备以及分组 分组 抽取功能 讲解所需要开发的功能 项目部署上线流程 ...

  2. 淘淘商城_day01_课堂笔记

    今日大纲 聊聊电商行业 电商行业发展 11.11 2015双11: 2016年: 预测:2017年的双11交易额将达到:1400亿 电商行业技术特点 淘淘商城简介 淘淘商城的前身 电商行业的概念 B2 ...

  3. 淘淘商城_day04_课堂笔记

    今日大纲 实现首页的大广告位功能 实现内容管理系统 首页的大广告 什么是大广告 JS效果: 点击下面的序号选择查询哪个广告 自动切换 点击图片查询具体的页面 以上是由前端团队来开发. 数据结构 说明: ...

  4. 淘淘商城_day02_课堂笔记

    今日大纲 学习Nginx的使用 实现商品的管理 新增商品 查询商品列表 编辑商品 删除商品 上架和下架商品 学习nginx 开发阶段中的环境 开发环境:自己的电脑 测试环境:提供给测试人员使用的环境 ...

  5. 淘淘商城_day10_课堂笔记

    今日大纲 Dubbo入门学习 使用dubbo优化单点登录系统 系统间服务调用方式 浏览器直接访问 浏览器发起请求,通过ajax或jsonp方式请求: Httpclient方式 系统与系统之间通过Htt ...

  6. 淘淘商城_day09_课堂笔记

    今日大纲 实现购物车 基于Mysql实现读写分离 购物车 需求描述 用户可以在登录状态下将商品添加到购物车 用户可以在未登录状态下将商品添加到购物车 用户可以使用购物车一起结算下单 用户可以查询自己的 ...

  7. 淘淘商城_day08_课堂笔记

    今日大纲 问题,如何实现商品数据的同步? 学习MQ(消息队列) 搭建RabbitMQ的环境 学习RabbitMQ的队列 学习Spring-Rabbit 使用RabbitMQ完成商品数据的同步 如何实现 ...

  8. 淘淘商城_day07_课堂笔记

    今日大纲 讲解订单系统 基于订单系统完成下单功能的开发 使用Solr完成商品的搜索功能 订单系统 说明:订单系统只是做讲解,不做开发. 导入taotao-order 表结构 订单表: 订单商品表: 疑 ...

  9. 淘淘商城_day06_课堂笔记

    今日大纲 实现单点登录系统 基于单点登录系统实现,用户的注册和登录 商品数据同步问题 问题 后台系统中将商品修改,前台系统没有进行数据的同步,导致前端系统不能够实时显示最新的数据. 解决 后台系统中商 ...

随机推荐

  1. [ios2] 利用钥匙串,在应用里保存用户密码的方法 【转】

    想在应用里保存帐号.密码等信息的话,直接存到 plist 里显然是不负责任的,自己折腾加密既麻烦又不能保证不被反编译破解.实际上苹果 iOS 和 Mac OS X 系统自带了一套敏感信息保存方案:&q ...

  2. iOS -不同模拟器字体适配

    1.先建立一个UILabel的分类 导入#import <objc/runtime.h>头文件 2.在.m文件中写入如下代码 //不同设备的屏幕比例(当然倍数可以自己控制) #define ...

  3. Redux超酷的开发工具Redux-Devtools

    超酷的开发工具 Redux-devtools redux-devtools是一个有趣而又高效的redux开发工具,如果你想直接在github上查看相关的内容,请前往这里.事实上,也鼓励大家养成在git ...

  4. angularjs的directive详解

    Directive(指令)笔者认为是AngularJ非常强大而有有用的功能之一.它就相当于为我们写了公共的自定义DOM元素或CLASS属性或ATTR属性,并且它不只是单单如此,你还可以在它的基础上来操 ...

  5. C# 修改iframe url

    一.修改本级的iframe url 首先在js中编写函数: <script type="text/javascript"> function reloadfrm2() ...

  6. weak引用变量是否线程安全

    1.在ARC出现之前,Objetive-C的内存管理需要手工执行release&retain操作,这些极大增加了代码的编写难度,同时带来很多的crash.  同时大量的delegate是unr ...

  7. SQL 判断 ‘表,存储过程,函数 ...’ 已是否存在

    下面为您介绍sql下用了判断各种资源是否存在的代码,需要的朋友可以参考下,希望对您学习sql的函数及数据库能够有所帮助.库是否存在if exists(select * from master..sys ...

  8. intellij idea 生成UUID

    Intellij IDEA 默认没启用这个功能 需要手动设置一下 , 下面是路径 Setting->Inspections->Serialization issues->Serial ...

  9. 约瑟夫问题-Josephus--及实例说明

    //---我保证所有的代码都已经通过测试---// 类似约瑟夫的问题又称为约瑟夫环.又称“丢手绢问题”. 这个问题来自于这样的一个关于著名犹太历史学家 Josephus传说: 在罗马人占领乔塔帕特后, ...

  10. 采用Jenkins搭建持续集成环境

    Jenkins介绍 Jenkins是一个CI工具.它可以根据设定持续定期编译,运行相应代码:运行UT或集成测试:将运行结果发送至邮件,或展示成报告... 这样做的最终目的是: 让项目保持健康的状态.如 ...