redis优化商城首页.——淘淘商城(十八)

需求

分析

  • 每次调用rest服务,如果都需要和mysql交互,则数据库的压力较大,响应时延也较大。特别是首页这种经常被访问的页面,这种现象尤其明显。所以需要在服务器设置缓存,一般使用redis。
  • 服务层在访问数据库之前,需要查看redis中是否存在对应的数据。如果存在则直接从redis中获取,否则从mysql中获得,并将获取的对象存储到redis中。
  • 后台管理工程更新mysql中的数据,需要进行缓存同步。有两种方法。
    1. 服务层提供清空redis缓存的服务,后台管理工程更新mysql之后,调用服务层的服务。
    2. 设置缓存过期时间。超时之后自动清空。
    3. 前者缓存同步及时,后者操作简单。

总结

  • 在业务内容的前后读取和写入redis缓存。
  • 使用第一种缓存同步方案。
  • 添加缓存之后的架构:
    7.structwithredis.png
  • 业务使用缓存和缓存同步的流程如下:
    7.indexflow.png

业务中使用缓存

  • 在taotao-rest中开发。

配置

  • pom.xml中添加jedis依赖。
    <dependency>
      <groupId>javax.servlet.jsp</groupId>
      <artifactId>jsp-api</artifactId>
      <scope>provided</scope>
    </dependency>
  • redis.properties中配置Ip、端口号,以及服务在redis中对应的key。
redis.host=127.0.0.1
redis.prot=6379

#redis中的key的值
#redis中内容的key
CONTENT_REDIS_KEY=CONTENT_REDIS_KEY
#redis中商品目录的key
ITEM_CATAGORY_LIST_REDIS_KEY=ITEM_CATAGORY_LIST_REDIS_KEY
  • spring-dao.xml中配置jedis连接池,用来操作redis,并自动扫描dao接口。
  <!-- redis客户端单机版 -->
  <bean id="redisClient" class="redis.clients.jedis.JedisPool">
    <constructor-arg name="host" value="${redis.host}"/>
    <constructor-arg name="port" value="${redis.prot}"/>
    <constructor-arg name="poolConfig" ref="jedisPoolConfig"/>
  </bean>
  <!-- redis连接池配置 -->
  <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
    <!-- 最大连接数 -->
    <property name="maxTotal" value="30"/>
    <!-- 最大空闲连接数 -->
    <property name="maxIdle" value="10"/>
    <!-- 每次释放连接的最大数目 -->
    <property name="numTestsPerEvictionRun" value="1024"/>
    <!-- 释放连接的扫描间隔(毫秒) -->
    <property name="timeBetweenEvictionRunsMillis" value="30000"/>
    <!-- 连接最小空闲时间 -->
    <property name="minEvictableIdleTimeMillis" value="1800000"/>
    <!-- 连接空闲多久后释放, 当空闲时间>该值 且 空闲连接>最大空闲连接数 时直接释放 -->
    <property name="softMinEvictableIdleTimeMillis" value="10000"/>
    <!-- 获取连接时的最大等待毫秒数,小于零:阻塞不确定的时间,默认-1 -->
    <property name="maxWaitMillis" value="1500"/>
    <!-- 在获取连接的时候检查有效性, 默认false -->
    <property name="testOnBorrow" value="true"/>
    <!-- 在空闲时检查有效性, 默认false -->
    <property name="testWhileIdle" value="true"/>
    <!-- 连接耗尽时是否阻塞, false报异常,ture阻塞直到超时, 默认true -->
    <property name="blockWhenExhausted" value="false"/>
  </bean>

  <!-- 扫描包加载Dao实现类 -->
  <context:component-scan base-package="com.taotao.rest.dao"/>

Dao层

  • com.taotao.rest.dao包下创建RedisDao接口,提供string、hash类型的增删查功能,以及过期时间和数字加一的功能。
public interface RedisDao {

    String set(String key, String value);

    String get(String key);

    Long del(String key);

    /**
     * 设置hash类型的值
     */
    Long hset(String key, String field, String value);

    String hget(String key, String field);

    Long hdel(String key, String field);

    /**
     * 对应的数字加1
     */
    Long incr(String key);

    /**
     * 字段过期时间(秒为单位)
     */
    Long ttl(String key);

    /**
     * 设置过期时间
     */
    Long expire(String key, Integer second);
}
  • impl包下创建RedisDao的单机版实现类。如果需要也可以使用集群版的实现类实现接口,用来替换单机版实现类。
@Repository
public class RedisDaoSingle implements RedisDao {

    @Autowired
    private JedisPool jedisPool;

    @Override
    public String set(String key, String value) {
        Jedis jedis = jedisPool.getResource();
        String result = jedis.set(key, value);
        jedis.close();
        return result;
    }

    @Override
    public String get(String key) {
        Jedis jedis = jedisPool.getResource();
        String result = jedis.get(key);
        jedis.close();
        return result;
    }

    @Override
    public Long del(String key) {
        Jedis jedis = jedisPool.getResource();
        Long result = jedis.del(key);
        jedis.close();
        return result;
    }

    @Override
    public Long hset(String key, String field, String value) {
        Jedis jedis = jedisPool.getResource();
        Long result = jedis.hset(key, field, value);
        jedis.close();
        return result;
    }

    @Override
    public String hget(String key, String field) {
        Jedis jedis = jedisPool.getResource();
        String result = jedis.hget(key, field);
        jedis.close();
        return result;
    }

    @Override
    public Long hdel(String key, String field) {
        Jedis jedis = jedisPool.getResource();
        Long result = jedis.hdel(key, field);
        jedis.close();
        return result;
    }

    @Override
    public Long incr(String key) {
        Jedis jedis = jedisPool.getResource();
        Long result = jedis.incr(key);
        jedis.close();
        return result;
    }

    @Override
    public Long ttl(String key) {
        Jedis jedis = jedisPool.getResource();
        Long result = jedis.ttl(key);
        jedis.close();
        return result;
    }

    @Override
    public Long expire(String key, Integer second) {
        Jedis jedis = jedisPool.getResource();
        Long result = jedis.expire(key, second);
        jedis.close();
        return result;
    }
}

Service层

  • 在ContentService的getContentList方法中添加redis的读取和写入,使用hash类型。key为rest.properties中的配置,field为内容分类id。
    /**
     * 主页内容在redis使用的key
     */
    @Value("${CONTENT_REDIS_KEY}")
    private String CONTENT_REDIS_KEY;

7.contentservice.png

发布缓存同步服务

  • 在taotao-rest开发。

Service层

  • 根据内容分类Id删除缓存。
@Service
public class RedisServiceImpl implements RedisService {

    @Value("${CONTENT_REDIS_KEY}")
    private String CONTENT_REDIS_KEY;

    @Autowired
    private RedisDao redisDao;

    @Override
    public TaotaoResult syncContent(long catagoryId) {
        try {
            redisDao.hdel(CONTENT_REDIS_KEY, String.valueOf(catagoryId));
        } catch (Exception e) {
            e.printStackTrace();
            return TaotaoResult.build(500, ExceptionUtil.getStackTrace(e));
        }
        return TaotaoResult.ok();
    }
}

Controller层

  • 接收url中的内容分类Id,调用service层。
@Controller
@RequestMapping("/cache/sync")
public class RedisController {

    @Autowired
    private RedisService redisService;

    @RequestMapping("/content/{catagoryId}")
    public TaotaoResult syncContent(@PathVariable Long catagoryId) {
        TaotaoResult result = redisService.syncContent(catagoryId);
        return result;
    }
}

调用缓存同步服务

  • taotao-manager中开发。

Service层

  • 在taotao-manaer-web中添加rest.properties,包含服务层url和内容缓存的url。
#服务层基础url
REST_BASE_URL=http://localhost:8081/rest
#内容缓存基础url
CONTENT_CACHE_URL=/cache/sync/content/
  • ContentService中addContent方法中,插入数据库之后调用服务层的缓存同步服务。
    7.contentadd.png

缓存同步的结果

  • 加载首页之后,首页有3个广告为。redis包含大广告位的信息,键值为CONTENT_REDIS_KEY。
    7.rediskeys.png
  • 后台管理工程添加新的大广告位之后,redis中的相关缓存被清空。
    7.rediskeysafteradd.png
  • 再次访问首页,大广告位内容从mysql加载,并写入redis,显示最新的5个大广告位。
    7.indexafteradd.png
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值