JAVA:SSM\分布式缓存\Redis\/spring data redis

Redis分布式缓存

 redis是一款开源的Key-Value数据库,存储数据是放在内存中,速度非常快,由C语言编写.企业开发通常采用redis来实现缓存.

业务流程

获取数据的时候先从redis中获取,如果获取到数据则直接返回,就不用访问数据库了,如果获取不到数据,可以从数据库中查询,查询到后放入redis中一份,下回就可以直接从redis中查询到,大大降低了数据库的高并发访问压力

持久化方案

rdb(默认支持,无需配置)分时持久化

  • 可以在配置文件中设定,多长时间持久化一次,持久化次数越少也就是硬盘的操作次数越少,速度快,但是如果在没有完成持久化之前,如果服务器断电,则内存中没有持久化的数据会丢失

aof实时持久化

  • 每次向redis中做增删改操作,都会将数据持久化到硬盘上,数据可靠性高,不会丢失,但是速度慢

redis可以同时使用RDB和AOF

redis中五大数据类型

  • string:字符串
  • hash:相当于map,是一种键值对形式.存入的数据是无序的,key不可以重复
  • list:存入其中的数据是有序的,存入其中的数据可以重复
  • set:存入其中的数据是无序的,存入其中的数据不可以重复
  • zset:存入其中的数据是有序的,存入其中的数据不可以重复

redis同类型技术

  • memcache是redis的同类型技术,底层也是使用C语言编写,memcache的速度和redis相当,但是memcache没有持久化方式

mongodb和redis区别

  • mongodb也是一个nosql数据库,存储的数据是非结构化的
  • redis:主要使用内存,有两种持久化方案,速度非常快,一般用做分布式缓存使用
  • mongodb:主要使用硬盘存储,所以不会担心数据丢失,速度介于redis和传统数据库之间,但是mongodb更擅长存储大文本数据,以及一些非结构化的数据,mongodb比redis的数据类型更加丰富

redis应用场景

  • 缓存(数据查询,短连接,新闻内容,商品内容等等)
  • 聊天室的在线好友列表
  • 任务队列(秒杀,抢购,12306等等)
  • 应用排行榜
  • 网站访问统计
  • 数据过期处理(可以精确到毫秒)
  • 分布式集群架构中的session分离

Spring Data Redis

  • Spring-data-redis是spring大家族的一部分,提供了在srping应用中通过简单的配置访问redis服务,对reids底层开发包(Jedis, JRedis, and RJC)进行了高度封装,RedisTemplate提供了redis各种操作、异常处理及序列化,支持发布订阅,并对spring 3.1 cache进行了实现。

Jedis 

  • Jedis是Redis官方推出的一款面向Java的客户端,提供了很多接口供Java语言调用。可以在Redis官网下载,当然还有一些开源爱好者提供的客户端,如Jredis、SRP等等,推荐使用Jedis

用Jedis做个案例

配置文件config.properties

host=localhost
port=6379
maxTotal=50
maxIdle=20

工具类JedisUtiles

package com.ayyy.core.utils;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import java.util.ResourceBundle;

/**

- 数据库连接池工具类
- 目的: 返回数据库连接对象Jedis
- 读取config配置文件
*/
public class JedisUtils {
//声明出连接池对象
private static JedisPool pool ;
//读取配置文件
static {
    ResourceBundle resourceBundle = ResourceBundle.getBundle("config");
    //获取服务器IP地址
    String host = resourceBundle.getString("host");
    //获取端口号
    int port = Integer.parseInt(resourceBundle.getString("port"));
    //获取最大连接数
    int maxTotal = Integer.parseInt( resourceBundle.getString("maxTotal"));
    //获取最大空闲连接
    int maxIdle = Integer.parseInt( resourceBundle.getString("maxIdle"));
    //创建连接池的配置信息对象
    JedisPoolConfig config = new JedisPoolConfig();
    //设置相关的信息
    config.setMaxTotal(maxTotal);
    config.setMaxIdle(maxIdle);
    //创建连接池对象
    pool = new JedisPool(config,host,port);
}
/**
  - 创建方法
  - 连接池对象,返回Jedis对象
*/
public static Jedis getJedis(){
return pool.getResource();
}
//释放资源方法
public static void close(Jedis jedis){
if(jedis!=null)
    jedis.close();
}
  public static void close(JedisPool pool){
    if(pool!=null)
        pool.close();
}
}

Service接口

package com.ayyy.core.service;
import com.ayyy.core.pojo.Category;
import java.util.List;

public interface CategoryService {
    //查询所有的分类数据
    List<Category> findAll();
}


Service实现类

package com.ayyy.core.service.impl;
import com.ayyy.core.dao.CategoryDao;
import com.ayyy.core.pojo.Category;
import com.ayyy.core.service.CategoryService;
import com.ayyy.core.utils.BeanFactory;
import com.ayyy.core.utils.JedisUtils;
import net.sf.json.JSONArray;
import redis.clients.jedis.Jedis;

import java.sql.SQLException;
import java.util.List;
public class CategoryServiceImpl implements CategoryService {
    //bean工厂,获取dao层接口实现类
    private CategoryDao categoryDao = BeanFactory.newInstance(CategoryDao.class);

    /**
     *  从redis数据库中查询导航数据
     *  不存在数据
     *    查询MySQL数据,取出category表数据
     *    数据转成JSON字符串,存储redis
     *
     *  数据存储在
     *    redis数据库存储的是字符串
     *    字符串转成集合返回
     */
    public List<Category> findAll(){
        List<Category> categoryList = null;
        //获取Redis数据库连接对象
        Jedis jedis = JedisUtils.getJedis();
        //获取字符串
        String category =  jedis.get("category");
        try {
            //判断是否有数据
            if (category == null) {
                //查询MySQL数据库,取出category表数据
                categoryList = categoryDao.findAll();
                //数据集合,转成JSON存储到redis
                //JSONArray.fromObject(categoryList).toString();
                jedis.set("category",JSONArray.fromObject(categoryList).toString());
            } else {
                //redis数据库有数据
                //category转成集合返回
                /**
                 * toList,JSON格式字符串转成集合List
                 * 参数: JSONArray对象
                 * 被转换后的集合的泛型的class对象
                 */
               // JSONArray.fromObject(category);
                categoryList = JSONArray.toList( JSONArray.fromObject(category),Category.class );
            }
        }catch (Exception ex){
            ex.printStackTrace();
        }finally {
            JedisUtils.close(jedis);
        }
        return  categoryList;
    }
}

Spring Data Redis案例

表现层

package com.ayyy.core.controller;
import com.ayyy.core.pojo.ad.Content;
import com.ayyy.core.service.ContentService;
import com.alibaba.dubbo.config.annotation.Reference;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;

@RestController
@RequestMapping("/content")
public class ContentController {

    @Reference
    private ContentService contentService;

    @RequestMapping("/findByCategoryId")
    public List<Content> findByCategoryId(Long categoryId) {
        List<Content> list = contentService.findByCategoryIdFromRedis(categoryId);
        return list;
    }
}

Service接口

package com.ayyy.core.service;
import com.ayyy.core.pojo.ad.Content;
import com.ayyy.core.pojo.ad.ContentCategory;
import com.ayyy.core.pojo.entity.PageResult;
import javax.naming.Context;
import java.util.List;

public interface ContentService {

    public List<Content> findByCategoryIdFromRedis(Long categoryId);


}

Service实现类

package com.ayyy.core.service;

import com.ayyy.core.dao.ad.ContentDao;
import com.ayyy.core.pojo.ad.Content;
import com.ayyy.core.pojo.ad.ContentQuery;
import com.ayyy.core.pojo.entity.PageResult;
import com.ayyy.core.util.Constants;
import com.alibaba.dubbo.config.annotation.Service;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import javax.naming.Context;
import java.util.List;

/**
 * 使用redis分布式缓存原则:
 * 一般关系型数据库作为我们的主数据库存储数据, 如果涉及到使用分布式缓存redis, 要保证redis中的数据
 * 和数据库中的数据要一致.
 */
@Service
public class ContentServiceImpl implements ContentService {

    @Autowired
    private ContentDao contentDao;

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 整个redis相当于一个大的hashMap, 在这个map中key是不可以重复的, 所以key是稀缺资源
     * key      value(value使用hash类型因为可以尽量少的占用key)
     *          field           value
     *          分类id            对应的这个分类的广告集合数据List<Content>
     *            001               List<Content>
     *            002               List<Content>
     *
     *
     */
    @Override
    public List<Content> findByCategoryIdFromRedis(Long categoryId) {
        //1. 首先根据分类id到redis中获取数据
        List<Content> contentList = (List<Content>)redisTemplate.boundHashOps(Constants.CONTENT_LIST_REDIS).get(categoryId);
        //2. 如果redis中没有数据则到数据库中获取数据
        if (contentList == null) {
            //3. 如果数据库中获取到数据, 则放入redis中一份
            contentList = findByCategoryId(categoryId);
            redisTemplate.boundHashOps(Constants.CONTENT_LIST_REDIS).put(categoryId, contentList);
        }
        return contentList;
    }
}

猜你喜欢

转载自blog.csdn.net/qq_42819446/article/details/89631092