国产美女主播视频一区_国产精品蜜臀在线观看_亚洲成人动漫一区_亚洲视屏在线播放

首頁(yè) > 時(shí)尚

SpringBoot整合Redis實(shí)現(xiàn)高并發(fā)數(shù)據(jù)緩存的示例講解 天天頭條

來(lái)源:腳本之家 時(shí)間:2023-06-24 16:03:49

目錄
什么是緩存為什么要用緩存Redis為什么這么快實(shí)現(xiàn)一個(gè)用戶信息的緩存方式一:利用RedisTemplate實(shí)現(xiàn) 導(dǎo)入依賴添加配置添加redis工具類及配置類service層controller層測(cè)試方式二:采用SpringBoot注解開啟緩存修改service層實(shí)現(xiàn)類代碼修改RedisConfig配置類

什么是緩存

緩存是?個(gè)高速數(shù)據(jù)交換的存儲(chǔ)器,使用它可以快速的訪問(wèn)和操作數(shù)據(jù)。

舉個(gè)通俗的例子。

小明經(jīng)營(yíng)著一家飯店,在剛開張的時(shí)候由于名氣不足,客源少,生意并不是很忙,平時(shí)沒(méi)事的時(shí)候就閑著,有客人來(lái)了再進(jìn)廚房安排做菜。隨著飯店的日益發(fā)展,此時(shí)的飯店已經(jīng)不同往日,有著大量的穩(wěn)定客源,并且在某些節(jié)假日的時(shí)候甚至爆滿。按照以前的做法,那肯定是行不通了,在用餐高峰期的時(shí)候因?yàn)閭洳吐龑?dǎo)致了客戶的長(zhǎng)時(shí)間等待,使得飯店的屢遭投訴。
為解決這一問(wèn)題,小明想到了一個(gè)辦法,可以在空閑的時(shí)候,提前將熱門的菜做完后放入保溫柜,等用餐高峰期時(shí)再拿出來(lái)加熱后就可以直接上菜,就規(guī)避了短時(shí)間內(nèi)大量客源而導(dǎo)致的備餐慢的問(wèn)題,通過(guò)這一方法,即使在高峰期,也能很好的應(yīng)對(duì)。


(資料圖片)

這就是緩存的本質(zhì),將熱點(diǎn)資源(高頻讀、低頻寫)提前放入離用戶最近、訪問(wèn)速度更快的地方,以提高訪問(wèn)速度。

為什么要用緩存

使用緩存后,效率會(huì)大大的提升,減少了不必要的資源消耗,提升了用戶體驗(yàn)。

redis的特點(diǎn):

redis支持?jǐn)?shù)據(jù)的持久化,可以將內(nèi)存中的數(shù)據(jù)保存在磁盤中,重啟的時(shí)候可以再次加在進(jìn)行使用。redis不僅僅支持簡(jiǎn)單的key-value類型的數(shù)據(jù),同時(shí)還提供list,set,zset,hash等數(shù)據(jù)結(jié)構(gòu)的儲(chǔ)存redis支持?jǐn)?shù)據(jù)的備份,即master-slave模式的數(shù)據(jù)備份

redis的優(yōu)勢(shì):

性能極高——redis能讀得的速度是110000次/s,寫的速度是81000次/s。豐富的數(shù)據(jù)類型——redis支持二進(jìn)制案例的Strings, Lists, Hashes, Sets 及 Ordered Sets 數(shù)據(jù)類型操作。原子——redis的所有操作都是原子性的,意思就是要么成功執(zhí)行要么失敗完全不執(zhí)行。單個(gè)操作是原子性的。多個(gè)操作也支持事務(wù),即原子性,通過(guò)multi和exec指令包起來(lái)。豐富的特性redis還支持publish/subscribe,通知,key過(guò)期等等特性

Redis為什么這么快

(1)完全基于內(nèi)存,數(shù)據(jù)存在內(nèi)存中,絕大部分請(qǐng)求是純粹的內(nèi)存操作,非常快速,跟傳統(tǒng)的磁盤文件數(shù)據(jù)存儲(chǔ)相比,避免了通過(guò)磁盤IO讀取到內(nèi)存這部分的開銷。

(2)數(shù)據(jù)結(jié)構(gòu)簡(jiǎn)單,對(duì)數(shù)據(jù)操作也簡(jiǎn)單。Redis中的數(shù)據(jù)結(jié)構(gòu)是專門進(jìn)行設(shè)計(jì)的,每種數(shù)據(jù)結(jié)構(gòu)都有一種或多種數(shù)據(jù)結(jié)構(gòu)來(lái)支持。Redis正是依賴這些靈活的數(shù)據(jù)結(jié)構(gòu),來(lái)提升讀取和寫入的性能。

(3)采用單線程,省去了很多上下文切換的時(shí)間以及CPU消耗,不存在競(jìng)爭(zhēng)條件,不用去考慮各種鎖的問(wèn)題,不存在加鎖釋放鎖操作,也不會(huì)出現(xiàn)死鎖而導(dǎo)致的性能消耗。

(4)使用基于IO多路復(fù)用機(jī)制的線程模型,可以處理并發(fā)的鏈接。

實(shí)現(xiàn)一個(gè)用戶信息的緩存

數(shù)據(jù)庫(kù)表結(jié)構(gòu):

CREATE TABLE `blade_user` (
  `id` bigint(20) NOT NULL COMMENT "主鍵",
  `tenant_id` varchar(12) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT "000000" COMMENT "租戶ID",
  `code` varchar(12) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT "用戶編號(hào)",
  `user_type` int(11) DEFAULT NULL COMMENT "用戶平臺(tái)",
  `account` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT "賬號(hào)",
  `password` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT "密碼",
  `name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT "昵稱",
  `real_name` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT "真名",
  `avatar` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT "頭像",
  `email` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT "郵箱",
  `phone` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT "手機(jī)",
  `birthday` datetime DEFAULT NULL COMMENT "生日",
  `sex` int(11) DEFAULT NULL COMMENT "性別",
  `role_id` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT "角色id",
  `dept_id` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT "部門id",
  `post_id` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT "崗位id",
  `create_user` bigint(20) DEFAULT NULL COMMENT "創(chuàng)建人",
  `create_dept` bigint(20) DEFAULT NULL COMMENT "創(chuàng)建部門",
  `create_time` datetime DEFAULT NULL COMMENT "創(chuàng)建時(shí)間",
  `update_user` bigint(20) DEFAULT NULL COMMENT "修改人",
  `update_time` datetime DEFAULT NULL COMMENT "修改時(shí)間",
  `status` int(11) DEFAULT NULL COMMENT "狀態(tài)",
  `is_deleted` int(11) DEFAULT "0" COMMENT "是否已刪除",
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC COMMENT="用戶表";

方式一:利用RedisTemplate實(shí)現(xiàn) 導(dǎo)入依賴

完整pom.xml文件:



    4.0.0
    
        org.springframework.boot
        spring-boot-starter-parent
        2.7.8
         
    
    com.redis.demo
    springboot-redis
    0.0.1-SNAPSHOT
    springboot-redis
    Demo project for Spring Boot
    
        1.8
    
    

        
            org.springframework.boot
            spring-boot-starter-web
        


        
            org.projectlombok
            lombok
            true
        
        
            org.springframework.boot
            spring-boot-starter-test
            test
        

        
        
            com.baomidou
            mybatis-plus-boot-starter
            3.4.2
        
        
            org.springframework.boot
            spring-boot-starter-data-redis
        

        
        
            mysql
            mysql-connector-java
            8.0.15
        

       
        
            cn.hutool
            hutool-all
            5.8.5
        
        
            com.alibaba
            fastjson
            1.2.41
        

        
            org.springframework.boot
            spring-boot-starter-cache
        

    

    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
                
                    
                        
                            org.projectlombok
                            lombok
                        
                    
                
            
        
    




添加配置

application.yml文件:

server:
  port: 8081

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://3.129.36.183:3306/test?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=UTF-8
    username: root
    password: root
  #redis
  redis:
    host: 3.129.36.183
    #Redis服務(wù)器連接端口
    port: 6379
    #Redis服務(wù)器連接密碼
    password: 123456

mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #開啟sql日志
    # 將帶有下劃線的表字段映射為駝峰格式的實(shí)體類屬性
    map-underscore-to-camel-case: true
  #配置類型別名所對(duì)應(yīng)的包
  type-aliases-package: com.redis.demo.entity
  #配置SQL輸出語(yǔ)句com.winsun.dataclean.mapper
  mapper-locations: com/redis/demo/dao/*.xml

添加redis工具類及配置類

RedisUtils:

package com.redis.demo.utils;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * Redis工具類
 *
 * @author
 */
@Component
public class RedisUtils {


    @Autowired
    private RedisTemplate redisTemplate;

    // =============================common============================

    /**
     * 指定緩存失效時(shí)間
     *
     * @param key  鍵
     * @param time 時(shí)間(秒)
     * @return
     */
    public boolean expire(String key, long time) {
        try {
            if (time > 0) {
                redisTemplate.expire(key, time, TimeUnit.SECONDS);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 根據(jù)key 獲取過(guò)期時(shí)間
     *
     * @param key 鍵 不能為null
     * @return 時(shí)間(秒) 返回0代表為永久有效
     */
    public long getExpire(String key) {
        return redisTemplate.getExpire(key, TimeUnit.SECONDS);
    }

    /**
     * 判斷key是否存在
     *
     * @param key 鍵
     * @return true 存在 false不存在
     */
    public boolean hasKey(String key) {
        try {
            return redisTemplate.hasKey(key);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 刪除緩存
     *
     * @param key 可以傳一個(gè)值 或多個(gè)
     */
    @SuppressWarnings("unchecked")
    public void del(String... key) {
        if (key != null && key.length > 0) {
            if (key.length == 1) {
                redisTemplate.delete(key[0]);
            } else {
                redisTemplate.delete(CollectionUtils.arrayToList(key));
            }
        }
    }

    // ============================String=============================

    /**
     * 普通緩存獲取
     *
     * @param key 鍵
     * @return 值
     */
    public Object get(String key) {
        return key == null ? null : redisTemplate.opsForValue().get(key);
    }

    /**
     * 普通緩存放入
     *
     * @param key   鍵
     * @param value 值
     * @return true成功 false失敗
     */
    public boolean set(String key, Object value) {
        try {
            redisTemplate.opsForValue().set(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 普通緩存放入并設(shè)置時(shí)間
     *
     * @param key   鍵
     * @param value 值
     * @param time  時(shí)間(秒) time要大于0 如果time小于等于0 將設(shè)置無(wú)限期
     * @return true成功 false 失敗
     */
    public boolean set(String key, Object value, long time) {
        try {
            if (time > 0) {
                redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
            } else {
                set(key, value);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 遞增
     *
     * @param key   鍵
     * @param delta 要增加幾(大于0)
     * @return
     */
    public long incr(String key, long delta) {
        if (delta < 0) {
            throw new RuntimeException("遞增因子必須大于0");
        }
        return redisTemplate.opsForValue().increment(key, delta);
    }

    /**
     * 遞減
     *
     * @param key   鍵
     * @param delta 要減少幾(小于0)
     * @return
     */
    public long decr(String key, long delta) {
        if (delta < 0) {
            throw new RuntimeException("遞減因子必須大于0");
        }
        return redisTemplate.opsForValue().increment(key, -delta);
    }

    // ================================Map=================================

    /**
     * HashGet
     *
     * @param key  鍵 不能為null
     * @param item 項(xiàng) 不能為null
     * @return 值
     */
    public Object hget(String key, String item) {
        return redisTemplate.opsForHash().get(key, item);
    }

    /**
     * 獲取hashKey對(duì)應(yīng)的所有鍵值
     *
     * @param key 鍵
     * @return 對(duì)應(yīng)的多個(gè)鍵值
     */
    public Map hmget(String key) {
        return redisTemplate.opsForHash().entries(key);
    }

    /**
     * HashSet
     *
     * @param key 鍵
     * @param map 對(duì)應(yīng)多個(gè)鍵值
     * @return true 成功 false 失敗
     */
    public boolean hmset(String key, Map map) {
        try {
            redisTemplate.opsForHash().putAll(key, map);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * HashSet 并設(shè)置時(shí)間
     *
     * @param key  鍵
     * @param map  對(duì)應(yīng)多個(gè)鍵值
     * @param time 時(shí)間(秒)
     * @return true成功 false失敗
     */
    public boolean hmset(String key, Map map, long time) {
        try {
            redisTemplate.opsForHash().putAll(key, map);
            if (time > 0) {
                expire(key, time);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 向一張hash表中放入數(shù)據(jù),如果不存在將創(chuàng)建
     *
     * @param key   鍵
     * @param item  項(xiàng)
     * @param value 值
     * @return true 成功 false失敗
     */
    public boolean hset(String key, String item, Object value) {
        try {
            redisTemplate.opsForHash().put(key, item, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 向一張hash表中放入數(shù)據(jù),如果不存在將創(chuàng)建
     *
     * @param key   鍵
     * @param item  項(xiàng)
     * @param value 值
     * @param time  時(shí)間(秒) 注意:如果已存在的hash表有時(shí)間,這里將會(huì)替換原有的時(shí)間
     * @return true 成功 false失敗
     */
    public boolean hset(String key, String item, Object value, long time) {
        try {
            redisTemplate.opsForHash().put(key, item, value);
            if (time > 0) {
                expire(key, time);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 刪除hash表中的值
     *
     * @param key  鍵 不能為null
     * @param item 項(xiàng) 可以使多個(gè) 不能為null
     */
    public void hdel(String key, Object... item) {
        redisTemplate.opsForHash().delete(key, item);
    }

    /**
     * 判斷hash表中是否有該項(xiàng)的值
     *
     * @param key  鍵 不能為null
     * @param item 項(xiàng) 不能為null
     * @return true 存在 false不存在
     */
    public boolean hHasKey(String key, String item) {
        return redisTemplate.opsForHash().hasKey(key, item);
    }

    /**
     * hash遞增 如果不存在,就會(huì)創(chuàng)建一個(gè) 并把新增后的值返回
     *
     * @param key  鍵
     * @param item 項(xiàng)
     * @param by   要增加幾(大于0)
     * @return
     */
    public double hincr(String key, String item, double by) {
        return redisTemplate.opsForHash().increment(key, item, by);
    }

    /**
     * hash遞減
     *
     * @param key  鍵
     * @param item 項(xiàng)
     * @param by   要減少記(小于0)
     * @return
     */
    public double hdecr(String key, String item, double by) {
        return redisTemplate.opsForHash().increment(key, item, -by);
    }

    // ============================set=============================

    /**
     * 根據(jù)key獲取Set中的所有值
     *
     * @param key 鍵
     * @return
     */
    public Set sGet(String key) {
        try {
            return redisTemplate.opsForSet().members(key);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 根據(jù)value從一個(gè)set中查詢,是否存在
     *
     * @param key   鍵
     * @param value 值
     * @return true 存在 false不存在
     */
    public boolean sHasKey(String key, Object value) {
        try {
            return redisTemplate.opsForSet().isMember(key, value);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 將數(shù)據(jù)放入set緩存
     *
     * @param key    鍵
     * @param values 值 可以是多個(gè)
     * @return 成功個(gè)數(shù)
     */
    public long sSet(String key, Object... values) {
        try {
            return redisTemplate.opsForSet().add(key, values);
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * 將set數(shù)據(jù)放入緩存
     *
     * @param key    鍵
     * @param time   時(shí)間(秒)
     * @param values 值 可以是多個(gè)
     * @return 成功個(gè)數(shù)
     */
    public long sSetAndTime(String key, long time, Object... values) {
        try {
            Long count = redisTemplate.opsForSet().add(key, values);
            if (time > 0)
                expire(key, time);
            return count;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * 獲取set緩存的長(zhǎng)度
     *
     * @param key 鍵
     * @return
     */
    public long sGetSetSize(String key) {
        try {
            return redisTemplate.opsForSet().size(key);
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * 移除值為value的
     *
     * @param key    鍵
     * @param values 值 可以是多個(gè)
     * @return 移除的個(gè)數(shù)
     */
    public long setRemove(String key, Object... values) {
        try {
            Long count = redisTemplate.opsForSet().remove(key, values);
            return count;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    // ===============================list=================================

    /**
     * 獲取list緩存的內(nèi)容
     *
     * @param key   鍵
     * @param start 開始
     * @param end   結(jié)束 0 到 -1代表所有值
     * @return
     */
    public List lGet(String key, long start, long end) {
        try {
            return redisTemplate.opsForList().range(key, start, end);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 獲取list緩存的長(zhǎng)度
     *
     * @param key 鍵
     * @return
     */
    public long lGetListSize(String key) {
        try {
            return redisTemplate.opsForList().size(key);
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * 通過(guò)索引 獲取list中的值
     *
     * @param key   鍵
     * @param index 索引 index>=0時(shí), 0 表頭,1 第二個(gè)元素,依次類推;index<0時(shí),-1,表尾,-2倒數(shù)第二個(gè)元素,依次類推
     * @return
     */
    public Object lGetIndex(String key, long index) {
        try {
            return redisTemplate.opsForList().index(key, index);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 將list放入緩存
     *
     * @param key   鍵
     * @param value 值
     * @return
     */
    public boolean lSet(String key, Object value) {
        try {
            redisTemplate.opsForList().rightPush(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 將list放入緩存
     *
     * @param key   鍵
     * @param value 值
     * @param time  時(shí)間(秒)
     * @return
     */
    public boolean lSet(String key, Object value, long time) {
        try {
            redisTemplate.opsForList().rightPush(key, value);
            if (time > 0)
                expire(key, time);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 將list放入緩存
     *
     * @param key   鍵
     * @param value 值
     * @return
     */
    public boolean lSet(String key, List value) {
        try {
            redisTemplate.opsForList().rightPushAll(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 將list放入緩存
     *
     * @param key   鍵
     * @param value 值
     * @param time  時(shí)間(秒)
     * @return
     */
    public boolean lSet(String key, List value, long time) {
        try {
            redisTemplate.opsForList().rightPushAll(key, value);
            if (time > 0)
                expire(key, time);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 根據(jù)索引修改list中的某條數(shù)據(jù)
     *
     * @param key   鍵
     * @param index 索引
     * @param value 值
     * @return
     */
    public boolean lUpdateIndex(String key, long index, Object value) {
        try {
            redisTemplate.opsForList().set(key, index, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 移除N個(gè)值為value
     *
     * @param key   鍵
     * @param count 移除多少個(gè)
     * @param value 值
     * @return 移除的個(gè)數(shù)
     */
    public long lRemove(String key, long count, Object value) {
        try {
            Long remove = redisTemplate.opsForList().remove(key, count, value);
            return remove;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }
}

RedisConfig:

package com.redis.demo.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.redis.demo.utils.MapUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;

import javax.annotation.PostConstruct;
import java.util.Map;

/**
 * @Author: laz
 * @CreateTime: 2023-02-20  11:55
 * @Version: 1.0
 *
 * 序列化
 */
@Configuration
public class RedisConfig {


    @Autowired
    private RedisTemplate redisTemplate;

    @PostConstruct
    public void init() {
        initRedisTemplate();
    }

    private void initRedisTemplate() {
        RedisSerializer stringSerializer = redisTemplate.getStringSerializer();
        redisTemplate.setKeySerializer(stringSerializer);
        redisTemplate.setHashKeySerializer(stringSerializer);
        redisTemplate.setValueSerializer(stringSerializer);
        redisTemplate.setHashValueSerializer(stringSerializer);
    }
}

開發(fā)mapper接口

package com.redis.demo.dao;


import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.redis.demo.entity.BladeUser;

/**
 * 

* 用戶表 Mapper 接口 *

* * @author laz * @since 2023-03-09 */ public interface BladeUserMapper extends BaseMapper { }

service層

IBladeUserService:

package com.redis.demo.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.redis.demo.entity.BladeUser;
import com.redis.demo.result.DealResult;

/**
 * 

* 用戶表 服務(wù)類 *

* * @author laz * @since 2023-03-09 */ public interface IBladeUserService extends IService { DealResult getById(Long id); }

BladeUserServiceImpl:

package com.redis.demo.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.redis.demo.constant.RedisConstants;
import com.redis.demo.dao.BladeUserMapper;
import com.redis.demo.entity.BladeUser;
import com.redis.demo.result.DealResult;
import com.redis.demo.service.IBladeUserService;
import com.redis.demo.status.CacheNameStatus;
import com.redis.demo.utils.RedisUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

/**
 * 

* 用戶表 服務(wù)實(shí)現(xiàn)類 *

* * @author laz * @since 2023-03-09 */ @Service public class BladeUserServiceImpl extends ServiceImpl implements IBladeUserService { @Autowired private RedisUtils redisUtils; @Override public DealResult getById(Long id) { String userKey = RedisConstants.CACHE_USER_KEY+id; Object user = redisUtils.get(userKey); if (!ObjectUtils.isEmpty(user)){ return DealResult.data(JSONUtil.toBean(JSONUtil.toJsonStr(user),BladeUser.class)); } BladeUser bladeUser = baseMapper.selectById(id); redisUtils.set(userKey, JSON.toJSONString(bladeUser)); return DealResult.data(bladeUser); } }

controller層

package com.redis.demo.controller;
import com.redis.demo.result.DealResult;
import com.redis.demo.service.IBladeUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RestController;

/**
 * 

* 用戶表 前端控制器 *

* * @author laz * @since 2023-03-09 */ @RestController @RequestMapping("/bladeUser") public class BladeUserController { @Autowired private IBladeUserService bladeUserService; @RequestMapping("getById/{id}") public DealResult getById(@PathVariable("id")Long id){ return bladeUserService.getById(id); } }

測(cè)試

啟動(dòng)項(xiàng)目,使用postman訪問(wèn)該接口,連續(xù)請(qǐng)求兩次,觀察響應(yīng)時(shí)長(zhǎng):

第一次:

第二次:

可以看到,第一次3.34s,第二次43ms,效率明顯提高!

方式二:采用SpringBoot注解開啟緩存

以方式一為準(zhǔn)

在啟動(dòng)類添加@EnableCaching注解

修改service層實(shí)現(xiàn)類代碼

package com.redis.demo.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.redis.demo.constant.RedisConstants;
import com.redis.demo.dao.BladeUserMapper;
import com.redis.demo.entity.BladeUser;
import com.redis.demo.result.DealResult;
import com.redis.demo.service.IBladeUserService;
import com.redis.demo.status.CacheNameStatus;
import com.redis.demo.utils.RedisUtils;
import lombok.AllArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

/**
 * 

* 用戶表 服務(wù)實(shí)現(xiàn)類 *

* * @author laz * @since 2023-03-09 */ @Service public class BladeUserServiceImpl extends ServiceImpl implements IBladeUserService { @Autowired private RedisUtils redisUtils; // @Override // public DealResult getById(Long id) { // // String userKey = RedisConstants.CACHE_USER_KEY+id; // Object user = redisUtils.get(userKey); // if (!ObjectUtils.isEmpty(user)){ // // return DealResult.data(JSONUtil.toBean(JSONUtil.toJsonStr(user),BladeUser.class)); // } // // BladeUser bladeUser = baseMapper.selectById(id); // redisUtils.set(userKey, JSON.toJSONString(bladeUser)); // return DealResult.data(bladeUser); // } @Cacheable(cacheNames = CacheNameStatus.BLADE_USER,keyGenerator = CacheNameStatus.KEY_GENERATOR) @Override public DealResult getById(Long id) { BladeUser bladeUser = baseMapper.selectById(id); return DealResult.data(bladeUser); } }

修改RedisConfig配置類

在配置類中添加自定義KeyGenerator

/**
     * 自定義KeyGenerator
     * @return
     */
    @Bean
    public KeyGenerator simpleKeyGenerator() {
        return (o, method, objects) -> {
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append(o.getClass().getSimpleName());
            stringBuilder.append(".");
            stringBuilder.append(method.getName());
            stringBuilder.append("[");
            for (Object obj : objects) {
                if(obj.toString().indexOf("Vo@")!= -1)
                {
                    Map map = MapUtil.getAttrFromModel(obj);
                    stringBuilder.append("[");
                    for(String item:map.keySet())
                    {
                        stringBuilder.append(",");
                        stringBuilder.append(map.get(item));
                    }

                    stringBuilder.append(",");
                    stringBuilder.deleteCharAt(stringBuilder.length() - 1);

                    stringBuilder.append("]");

                }
                else {
                    stringBuilder.append(obj);
                    stringBuilder.append(",");
                }

            }

            stringBuilder.append("]");
            return stringBuilder.toString();
        };
    }

:關(guān)于 @Cacheable注解的參數(shù),不懂的可以點(diǎn)擊查看。

重啟項(xiàng)目,再次訪問(wèn)以上接口,觀察響應(yīng)時(shí)間:

第一次:

第二次:

可以看到,第一次2.52s,第二次44ms,效率明顯提高!

通過(guò)Redis可視化工具觀察緩存數(shù)據(jù):

通過(guò)觀察緩存數(shù)據(jù)大小可知:方式一449字節(jié),方式二976字節(jié),如果從內(nèi)存占用大小的角度考慮,博主認(rèn)為使用RedisTemplate方式做緩存更合適,因?yàn)檫@種方式所占內(nèi)存相對(duì)較少。

以上就是該篇文章的所有內(nèi)容,代碼已上傳至git:https://gitee.com/lianaozhe/springboot-redis.git

到此這篇關(guān)于SpringBoot整合Redis實(shí)現(xiàn)高并發(fā)數(shù)據(jù)緩存的文章就介紹到這了,更多相關(guān)SpringBoot Redis高并發(fā)數(shù)據(jù)緩存內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)稿件

SpringBoot整合Redis實(shí)現(xiàn)高并發(fā)數(shù)據(jù)緩存的示例講解 天天頭條

全球看熱訊:古裝廠牌到全能玩家,年均爆款的西嘻影業(yè)提供了影視公司的生存法

【旗艦】7.5見?紅魔8S Pro發(fā)布時(shí)間曝光 國(guó)內(nèi)首臺(tái)8G2超頻版 全球百事通

廈門社保要交滿多少年,廈門社保繳費(fèi)年限如何法規(guī)的

烏克蘭基輔市遭導(dǎo)彈襲擊 已致3人死亡_焦點(diǎn)信息

世界新資訊:北京市氣象臺(tái)發(fā)布高溫紅色預(yù)警信號(hào) 最高氣溫可達(dá)37-40℃

世界信息:上海2022年退休工資調(diào)整細(xì)則

萬(wàn)圣節(jié)門鈴和禮物創(chuàng)意,男生浪漫到底可行嗎?如何為這個(gè)節(jié)日增添驚喜?知乎專家來(lái)為你解答!

風(fēng)吹十里荷花香 “蓮”通鄉(xiāng)村“致富路”

美媒稱波蘭曾作為“北溪”爆炸行動(dòng)基地 波蘭:完全不屬實(shí)!

世界新動(dòng)態(tài):全國(guó)鐵路今天預(yù)計(jì)發(fā)送旅客1515萬(wàn)人次

燃?xì)忾y門怎樣操作,你都了解嗎?請(qǐng)收藏轉(zhuǎn)發(fā)!

【當(dāng)前熱聞】戒糖就是甜的不吃嗎

農(nóng)業(yè)機(jī)械化有力保障夏糧收獲

全球資訊:三天漲超20%!工業(yè)富聯(lián)最新發(fā)聲

最新消息:外三元毛豬

速遞!白玉蘭視帝視后出爐,雷佳音打敗張譯獲得視帝,吳越視后實(shí)至名歸

我二次元的朋友們(8)|天天微資訊

可以接受友情變愛情的三個(gè)星座,日久生情 每日消息

六月第4期:六大策略組合表現(xiàn):寬信用本周收益率為0.5%

保護(hù)知識(shí)產(chǎn)權(quán)激發(fā)創(chuàng)新活力

端午節(jié)了還沒(méi)學(xué)會(huì)包粽子?用VR試試,幫你成為特級(jí)廚師!

天天即時(shí)看!CK3歷史人物維基翻譯(166):弗沙塔將軍

環(huán)球今頭條!美媒:福特?cái)M進(jìn)行新一輪裁員,主要針對(duì)美國(guó)正式員工

端午假期廈門舉辦各式活動(dòng) 市民游客感受傳統(tǒng)節(jié)日魅力

廈門天馬高世代生產(chǎn)線項(xiàng)目順利推進(jìn)

我國(guó)最長(zhǎng)深水油氣管道進(jìn)入調(diào)試階段

今日精選:風(fēng)吹十里荷花香 “蓮”通鄉(xiāng)村“致富路”

終究走到了這一步,烏克蘭干了一件荒唐的事

薛麗萍家庭被評(píng)為第三屆江蘇省文明家庭


主站蜘蛛池模板: 久99久在线| 日本一区二区三不卡| 日韩欧美精品在线不卡| 99精品视频在线看| 深夜福利一区二区| 久久亚洲国产精品日日av夜夜| 亚洲一区高清| 青青青国产在线视频| 精品中文字幕视频| 99亚洲国产精品| 日本久久久久久| 97精品视频在线播放| 一本久久a久久精品vr综合| 激情五月婷婷六月| 久久精品国产美女| 日韩视频―中文字幕| 天天干天天色天天爽| 三级三级久久三级久久18| 久久精品亚洲精品| 韩国v欧美v日本v亚洲| 色妞一区二区三区| 无码av天堂一区二区三区| 亚洲精品电影在线一区| 一区二区视频在线播放| 久久精品午夜一区二区福利| **亚洲第一综合导航网站| 97色在线播放视频| 日韩中文视频免费在线观看| 日韩精品视频在线观看视频| 欧美日韩免费高清| 久久亚洲免费| 国产日韩欧美精品在线观看| 久久久久久久久久福利| 亚洲精品日韩激情在线电影| 91高潮在线观看| 欧美日本高清一区| 日韩在线视频网| 欧美激情国产精品日韩| 久久久99国产精品免费| 久久久久久成人精品| 久久99精品久久久久久噜噜 |