1.系统优化策略

阐明:引入缓存机制能够无效的升高用户拜访物理设施的频次,从而进步响应速度.

2.如何设计缓存

1.缓存数据如何存储? 应该采纳什么样的数据结构呢? K-V key的唯一性
2.缓存数据的容量大小 应该动静保护缓存数据,将不须要的数据提前删除. LRU算法/LFU算法/随机算法/TTL算法
3.缓存数据保留到内存中,然而内存的特点断电即擦除. 定期将内存数据长久化(写入磁盘中)
4.单台缓存服务器性能有余,所以个别须要搭建集群(实现高可用).
5.应用C语言开发.

3.Redis缓存服务

3.1什么是Redis

Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它能够用作数据库、缓存和消息中间件。 它反对多种类型的数据结构,如 字符串(strings), 散列(hashes), 列表(lists), 汇合(sets), 有序汇合(sorted sets) 与范畴查问, bitmaps, hyperloglogs 和 天文空间(geospatial) 索引半径查问。 Redis 内置了 复制(replication),LUA脚本(Lua scripting), LRU驱动事件(LRU eviction),事务(transactions) 和不同级别的 磁盘长久化(persistence), 并通过 Redis哨兵(Sentinel)和主动 分区(Cluster)提供高可用性(high availability)。
速度: 读: 11.2万/秒 写:8.6万/秒 50万/秒

3.2上传Redis

1).上传redis

2).解压redis服务
[root@localhost src]# tar -xvf redis-5.0.4.tar.gz
3).挪动文件/批改文件名称

3.3装置Redis

阐明:在Redis根目录中执行如下命令
1).make

2). make install

3.4 批改redis配置文件

批改redis根目录下的redis.conf文件
1).去除IP绑定

2).批改保护模式

3).开启后盾启动

4.Redis服务器命令

阐明: Redis服务在运行时,必须依赖于配置文件 redis.conf. 操作redis时最好在根目录中操作
1).启动redis

redis-server redis.conf


2).进入redis客户端

redis-cli -p 6379
ctrl + c 退出客户端


3).敞开redis服务器

redis-cli -p 6379 shutdown


办法二:
阐明: 如果操作的端口号是默认端口6379 则能够省略不写.
1).启动redis

redis-server redis.conf

2).进入redis客户端

redis-cli 

3).敞开redis服务器

redis-cli shutdown

4.SpringBoot整合Redis

4.1 整合入门案例

4.1.1 导入jar包

`<!--spring整合redis redisTemplate Spring封装jedis高级API-->        <dependency>            <groupId>redis.clients</groupId>            <artifactId>jedis</artifactId>        </dependency>        <dependency>            <groupId>org.springframework.data</groupId>            <artifactId>spring-data-redis</artifactId>        </dependency>` 

4.1.2 实现测试案例

4.2 测试根本命令

package com.jt.test;import org.junit.jupiter.api.Test;import org.springframework.boot.test.context.SpringBootTest;import redis.clients.jedis.Jedis;import redis.clients.jedis.params.SetParams;//@SpringBootTestpublic class TestRedis {    //链接服务: IP地址:端口    @Test    public void testSetGet() throws InterruptedException {        Jedis jedis = new Jedis("192.168.126.129",6379);        jedis.flushAll();   //先清空redis缓存        //1.存取redis        jedis.set("key1", "天天向上");        String value = jedis.get("key1");        System.out.println(value);        //2.判断key是否存在        if(jedis.exists("key1")){            jedis.set("key1", "好好学习,天天向上");        }else{            jedis.set("key1", "天天开心");        }        //3.为key增加超时工夫        jedis.expire("key1", 10);        Thread.sleep(2000);        System.out.println("残余存活工夫:"+jedis.ttl("key1"));        //4.撤销残余超时工夫        jedis.persist("key1");        System.out.println("撤销胜利!!");    }}

4.2.1 setNx/setEx/set命令

   /**     * 需要: 如果数据不存在,则将数据批改     */    @Test    public void testSetNx(){        Jedis jedis = new Jedis("192.168.126.129",6379);        jedis.set("key1", "aaa");        //如果key不存在,则赋值        jedis.setnx("key1", "测试方法");        System.out.println(jedis.get("key1"));    }    /**     * 需要: 实现超时工夫的设定与赋值操作的原子性.     * 考点: 为数据设定超时工夫时,切记满足原子性要求.     *      否则会呈现key永远不能删除的景象     */    @Test    public void testSetEx(){        Jedis jedis = new Jedis("192.168.126.129",6379);        /*jedis.set("key2", "bbb");        jedis.expire("key2", 3);*/        //???数据超时之后肯定会被删除吗???  错的        jedis.setex("key2", 10, "bbb");    }    /**     * 需要: 如果数据存在时,才会批改数据,并且为数据增加超时工夫10秒(原子性).     * 参数阐明:     *      NX: 只有数据不存在时,才会赋值.     *      XX: 只有数据存在时,才会赋值.     *      EX: 秒     *      PX: 毫秒     */    public void testSet(){        Jedis jedis = new Jedis("192.168.126.129",6379);       /* if(jedis.exists("key3")){            jedis.setex("key3",10 ,"ccc");        }*/        SetParams setParams = new SetParams();        setParams.xx().ex(10);        //将所有的操作采纳原子性的形式进行管制        jedis.set("key3", "ccc", setParams);    } 

4.2.2 测试hash

   /**     * HASH测试     */    @Test    public void testHash(){        Jedis jedis = new Jedis("192.168.126.129",6379);        jedis.hset("person", "id", "100");        jedis.hset("person", "name", "tomcat猫");        System.out.println(jedis.hgetAll("person"));    }

4.2.3 测试List

   /**     * LIST汇合测试     */    @Test    public void testList(){        Jedis jedis = new Jedis("192.168.126.129",6379);        jedis.lpush("list", "1","2","3","4");        String value = jedis.rpop("list");        System.out.println(value);    }

4.2.4 测试事务

   /**     * Set汇合测试     *  1. sadd  新增元素     *  2. SCARD  获取元素数量     *  3. SINTER key1 key2  获取元素的交加     *  4. SMEMBERS set      获取汇合元素     *  demo本人补一下     */    @Test    public void testMulti(){        Jedis jedis = new Jedis("192.168.126.129",6379);        //开启事务        Transaction transaction = jedis.multi();        try {            transaction.set("a", "a");            transaction.set("b", "b");            //提交事务            transaction.exec();        }catch (Exception e){            //回滚事务            transaction.discard();        }    } 

5.SpringBoot整合Redis的理论使用

5.1 编辑properties配置文件

5.2 编辑配置类

package com.jt.config;import org.springframework.beans.factory.annotation.Value;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.PropertySource;import redis.clients.jedis.Jedis;@Configuration//标识是个配置类,个别与@Bean注解连用@PropertySource("classpath:/properties/redis.properties")public class RedisConfig {    @Value("${redis.host}")    private String host;    @Value("${redis.port}")    private Integer port;    @Bean public Jedis jedis(){        return new Jedis(host,port);    }}

6.ObjectMapperUtil实现

6.1 业务需要

阐明:在业务中通常须要将业务对象转化为JSON数据.须要通过工具API进行手动的转化.

6.2 入门案例

public class TestObjectMapper {    //objectMapper入门案例    //2. 将JSON转化为对象    @Test    public void testObject() throws JsonProcessingException {        //1. 将对象转化为JSON        ItemDesc itemDesc = new ItemDesc();        itemDesc.setItemId(100L)                .setItemDesc("我是一个测试数据")                .setCreated(new Date())                .setUpdated(itemDesc.getCreated());        ObjectMapper objectMapper = new ObjectMapper();        String json = objectMapper.writeValueAsString(itemDesc);        System.out.println(json);        //2.将JSON转化为对象        ItemDesc desc = objectMapper.readValue(json, ItemDesc.class);        System.out.println(desc);    }    @Test    public void testList() throws JsonProcessingException {        List<ItemDesc> list = new ArrayList<>();        ItemDesc itemDesc = new ItemDesc();        itemDesc.setItemId(100L).setItemDesc("我是一个测试数据").setCreated(new Date()).setUpdated(itemDesc.getCreated());        ItemDesc itemDesc2 = new ItemDesc();        itemDesc2.setItemId(200L).setItemDesc("我是一个测试数据").setCreated(new Date()).setUpdated(itemDesc.getCreated());        list.add(itemDesc);        list.add(itemDesc2);        //1. 将对象转化为JSON        ObjectMapper objectMapper = new ObjectMapper();        String json = objectMapper.writeValueAsString(list);        System.out.println(json);        //2.将JSON转化为对象        List<ItemDesc> list2 = objectMapper.readValue(json,list.getClass());        System.out.println(list2);    }}

6.3 编辑ObjectMapperUtil

public class ObjectMapperUtil {    private static final ObjectMapper MAPPER = new ObjectMapper();    public static String toJSON(Object target){        try {            return MAPPER.writeValueAsString(target);        } catch (JsonProcessingException e) {            e.printStackTrace();            //将查看异样转化为运行时异样.            throw new RuntimeException(e);        }    }    public static <T> T toObject(String json,Class<T> targetClass){        try {            return MAPPER.readValue(json, targetClass);        } catch (JsonProcessingException e) {            e.printStackTrace();            throw new RuntimeException(e);        }    }}

7.实现商品分类缓存操作

7.1 编辑ItemController

 /**     * 业务需要: 实现商品分类树形构造展示     * url地址:   http://localhost:8091/item/cat/list     * 参数:      id= 父级节点的ID     * 返回值:    List<EasyUITree>     */    @RequestMapping("/list")    public List<EasyUITree> findItemCatList(Long id){        //临时只查问一级商品分类信息        long parentId = (id==null?0:id);        //return itemCatService.findItemCatList(parentId);        return itemCatService.findItemCatCache(parentId);    }

7.2 编辑ItemService

package com.jt.service;import com.baomidou.mybatisplus.core.conditions.query.Query;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;import com.jt.mapper.ItemCatMapper;import com.jt.pojo.ItemCat;import com.jt.util.ObjectMapperUtil;import com.jt.vo.EasyUITree;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import redis.clients.jedis.Jedis;import java.util.ArrayList;import java.util.List;@Servicepublic class ItemCatServiceImpl implements ItemCatService{    @Autowired    private ItemCatMapper itemCatMapper;    @Autowired(required = false)  //相似于懒加载    private Jedis jedis;    @Override    public ItemCat findItemCatById(Long itemCatId) {        return itemCatMapper.selectById(itemCatId);    }    /**     * 1.依据parentId 查问子级目录信息     * 2.获取ItemCatList汇合,之后将List汇合转化为VOList汇合     * 3.返回数据     * @param parentId     * @return     */    @Override    public List<EasyUITree> findItemCatList(long parentId) {        QueryWrapper<ItemCat> queryWrapper = new QueryWrapper<>();        queryWrapper.eq("parent_id", parentId);        List<ItemCat> catList = itemCatMapper.selectList(queryWrapper);        //2 list汇合转化        List<EasyUITree> treeList = new ArrayList<>(catList.size());        for (ItemCat itemCat : catList){            long id = itemCat.getId();            String text = itemCat.getName();            String state = itemCat.getIsParent()?"closed":"open"; //是父级,默认应该closed            EasyUITree easyUITree = new EasyUITree(id, text, state);            treeList.add(easyUITree);        }        return treeList;    }    /**     * 实现步骤:     *      1.先定义key     ITEM_CAT_PARENT::0     *      2.先查问缓存     *          有  true    获取缓存数据之后,将JSON转化为对象 之后返回     *          没有 false   应该查询数据库, 之后将数据保留到redis中. 默认30天超时.     * * @param parentId     * @return     */    @Override    public List<EasyUITree> findItemCatCache(long parentId) {        Long startTime = System.currentTimeMillis();        List<EasyUITree> treeList = new ArrayList<>();        //1.定义key        String key = "ITEM_CAT_PARENT::"+parentId;        //2.从缓存中获取对象        if(jedis.exists(key)){            //存在  间接获取缓存数据,之后转化为对象            String json = jedis.get(key);            treeList =  ObjectMapperUtil.toObject(json,treeList.getClass());            System.out.println("查问redis缓存,获取数据");            long endTime = System.currentTimeMillis();            System.out.println("耗时:"+(endTime-startTime)+"毫秒");        }else{            //不存在  应该先查询数据库,之后将数据保留到缓存中.            treeList = findItemCatList(parentId);            String json = ObjectMapperUtil.toJSON(treeList);            jedis.setex(key, 7*24*60*60, json);            System.out.println("查询数据库获取后果");            long endTime = System.currentTimeMillis();            System.out.println("耗时:"+(endTime-startTime)+"毫秒");        }        return treeList;    }}