日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

JAVA数据缓存之内存缓存

發(fā)布時(shí)間:2023/12/10 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JAVA数据缓存之内存缓存 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

JAVA數(shù)據(jù)緩存之內(nèi)存緩存

簡(jiǎn)要介紹

java內(nèi)存緩存其實(shí)就是本地緩存 , 實(shí)現(xiàn)方法一般是從數(shù)據(jù)庫(kù)查詢出需要緩存的數(shù)據(jù)然后放到map里 ,根據(jù)需求可分為增量緩存和全量緩存,核心思想就是將想要查詢數(shù)據(jù)庫(kù)的用戶攔住,從內(nèi)存緩存中拿到想要的數(shù)據(jù)返回給用戶。

使用場(chǎng)景

1.前臺(tái)查詢用戶量比較大, 一直去查數(shù)據(jù)庫(kù)會(huì)對(duì)數(shù)據(jù)庫(kù)造成壓力。 2.數(shù)據(jù)量比較大 從大數(shù)據(jù)量里邊拿一小部分?jǐn)?shù)據(jù),一般是一個(gè)人的相關(guān)數(shù)據(jù)。 3.非集群環(huán)境 集群環(huán)境使用內(nèi)存緩存會(huì)使內(nèi)存的使用量變化過(guò)大,集群環(huán)境數(shù)據(jù)量不是特別大推薦redis數(shù)據(jù)緩存 ,數(shù)據(jù)量過(guò)大使用mogoDB緩存。4.數(shù)據(jù)量特別大不建議使用,過(guò)度使用內(nèi)存存儲(chǔ)會(huì)對(duì)服務(wù)器造成壓力。5.緩存之前一定得試一下你那個(gè)查詢到底多少秒能查出來(lái),如果查詢都很慢,然后你又要求數(shù)據(jù)緩存做成實(shí)時(shí)的(比如一秒一刷)這樣會(huì)造成線程隊(duì)列堆積,這樣會(huì)把服務(wù)直接刷死。

特性

1.直接使用JAVA內(nèi)存緩存查詢速度是比redis快的。2.不能持久化(mogoDB和redis可以持久化)。

數(shù)據(jù)緩存前期準(zhǔn)備

數(shù)據(jù)緩存最不可或缺的步驟為定時(shí)任務(wù),這里我們使用的是spring提供的定時(shí)任務(wù) ,配合cron表達(dá)式實(shí)現(xiàn)定時(shí)刷新緩存, 真正的線上環(huán)境絕對(duì)不是只緩存一種數(shù)據(jù),所以定時(shí)任務(wù)一定得是多線程的,不能為串行執(zhí)行,所以需要進(jìn)行如下配置。 import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.annotation.SchedulingConfigurer; import org.springframework.scheduling.config.ScheduledTaskRegistrar;import java.util.concurrent.Executor; import java.util.concurrent.Executors;/*** 沒(méi)有此配置,則schedule為單線程串行執(zhí)行*/ @Configuration @EnableScheduling public class ScheduleConfig implements SchedulingConfigurer {@Overridepublic void configureTasks(ScheduledTaskRegistrar taskRegistrar) {taskRegistrar.setScheduler(taskExecutor());}//配置線程池---觸發(fā)器和任務(wù)共用的@Bean(destroyMethod="shutdown")public Executor taskExecutor() {return Executors.newScheduledThreadPool(10);} }

初始化數(shù)據(jù)

使用數(shù)據(jù)緩存之前首先需要初始化好裝數(shù)據(jù)的map和記錄增量緩存的緩存時(shí)刻(寫(xiě)增量緩存的話是需要記錄上一次緩存的時(shí)間,在這個(gè)時(shí)間之后的數(shù)據(jù)需要進(jìn)行緩存),這兩種數(shù)據(jù)都寫(xiě)成全局變量也就是定義在類(lèi)里邊方法上邊。 //因?yàn)橐褂迷隽烤彺? 首先初始化用到的時(shí)間private Timestamp firmDataTime = null;//初始化hashMap用來(lái)存儲(chǔ)緩存值public static ConcurrentHashMap<Integer , Firm> firmData = new ConcurrentHashMap<>();

全量緩存使用場(chǎng)景

數(shù)據(jù)在一定時(shí)間內(nèi)是不變的,或者在特定的時(shí)間進(jìn)行改變?nèi)缓笠欢〞r(shí)間內(nèi)不改變(比如市場(chǎng)結(jié)算時(shí)候的分成數(shù)據(jù),市場(chǎng)會(huì)在每天閉市后進(jìn)行結(jié)算分成,意思是這個(gè)數(shù)據(jù)會(huì)在每天閉市后生成,并在下一次閉市前保持不變)

全量緩存代碼塊簡(jiǎn)要解釋

從1號(hào)開(kāi)始每天進(jìn)行一次全量緩存 首先清理緩存,然后查數(shù)據(jù)庫(kù),然后把數(shù)據(jù)庫(kù)的數(shù)據(jù)裝到map里邊,邏輯是比較簡(jiǎn)單的。

全量緩存代碼展示

//全量緩存@Scheduled(cron = "0 0 0 1/1 * ? ")public void cacheAllFirm(){firmData = null;List<Firm> firms = firmRepo.findAll();ConcurrentHashMap<Integer , Firm> allFirmMap= new ConcurrentHashMap<>();for(Firm firm : firms){allFirmMap.put(firm.getFirmId() , firm);}firmData = allFirmMap;}

增量緩存使用場(chǎng)景

一般其實(shí)做數(shù)據(jù)緩存的話是使用增量緩存,核心思想就是只緩存修改或新增的數(shù)據(jù),緩存的數(shù)據(jù)少了,自然速度就快了。

增量緩存代碼塊簡(jiǎn)要解釋

這里寫(xiě)的是一個(gè)每三秒進(jìn)行一次增量緩存,首先記錄一下當(dāng)前時(shí)間,然后減去一個(gè)緩沖時(shí)間(意思就是每次增量緩存需要多緩存一些,防止因?yàn)槿蝿?wù)的執(zhí)行或者數(shù)據(jù)的變動(dòng)少緩存數(shù)據(jù),這個(gè)緩沖時(shí)間一般設(shè)置成2秒3秒左右,不用擔(dān)心會(huì)多緩存數(shù)據(jù),因?yàn)閙ap 的存儲(chǔ)特性key是唯一的,不會(huì)重復(fù)存儲(chǔ))如果map是空的首先就得進(jìn)行一次全量緩存,不為空才增量 只查詢記錄緩存時(shí)間之后的數(shù)據(jù),并put到map里,每次裝完數(shù)據(jù)記錄一個(gè)時(shí)間。

增量緩存代碼展示

@Scheduled(cron = "*/3 * * * * ? ")public void cacheFirm(){log.info("每三秒增量緩存一次firm");Long time = new Timestamp(System.currentTimeMillis()).getTime() - 3000;if(firmData.isEmpty()){List<Firm> v = firmRepo.findAll();//第一次緩存先全量緩存一次log.info("全量緩存開(kāi)始");addDateFirm(v , time);}else{List<Firm> v = firmRepo.findAllByUpdateTimeAfterOrCreateTimeAfter(firmDataTime , firmDataTime);//進(jìn)行增量緩存log.info("增量緩存開(kāi)始");addDateFirm(v , time);}}private void addDateFirm(List<Firm> firms , Long time){if(firms != null && firms.size() > 0 ){for(Firm firm : firms){firmData.put(firm.getFirmId() , firm);}}firmDataTime = new Timestamp(time);}

以下是內(nèi)存緩存的全部測(cè)試代碼(包括以上舉的例子)

controller

import com.tjdami.zs.test.jpa.model.Firm; import com.tjdami.zs.test.service.TestService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController;/*** @Auther: Zyy* @Date: 2020/12/7 10:34* @Description:*/ @Api(value = "測(cè)試服務(wù)", description = "通用測(cè)試服務(wù)") @RequestMapping("/test") @RestController @Slf4j public class TestController {@Autowiredprivate TestService testService;@RequestMapping(value = "/cacheFirm")@ApiOperation(value = "查看客戶信息", httpMethod = "POST", notes = "查看客戶信息")public Firm distribute(@RequestHeader("firmId") String firmId) throws Exception {return testService.getFirmCache(Integer.valueOf(firmId));}}

service

import com.tjdami.zs.test.cache.TextCache; import com.tjdami.zs.test.jpa.model.Firm; import org.springframework.stereotype.Service;/*** @Auther: Zyy* @Date: 2020/12/7 11:02* @Description:*/ @Service public class TestService {public Firm getFirmCache(Integer firmId) throws Exception {Firm firm = TextCache.firmData.get(firmId);return firm;} }

緩存核心

import com.tjdami.zs.test.jpa.model.Firm; import com.tjdami.zs.test.jpa.repo.FirmRepo; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component;import java.sql.Timestamp; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ConcurrentHashMap;/*** @Auther: Zyy* @Date: 2020/12/7 11:17* @Description:*/ @Component @Slf4j public class TextCache {@Autowiredprivate FirmRepo firmRepo;//因?yàn)橐褂迷隽烤彺? 首先初始化用到的時(shí)間private Timestamp firmDataTime = null;private Timestamp firmDataListTime = null;//初始化hashMap用來(lái)存儲(chǔ)緩存值public static ConcurrentHashMap<Integer , Firm> firmData = new ConcurrentHashMap<>();//初始化一個(gè)存儲(chǔ)firm集合的map集合public static ConcurrentHashMap<Integer , List<Firm>> firmDataList = new ConcurrentHashMap<>();@Scheduled(cron = "*/3 * * * * ? ")public void cacheFirm(){log.info("每三秒增量緩存一次firm");Long time = new Timestamp(System.currentTimeMillis()).getTime() - 3000;if(firmData.isEmpty()){List<Firm> v = firmRepo.findAll();//第一次緩存先全量緩存一次log.info("全量緩存開(kāi)始");addDateFirm(v , time);}else{List<Firm> v = firmRepo.findAllByUpdateTimeAfterOrCreateTimeAfter(firmDataTime , firmDataTime);//進(jìn)行增量緩存log.info("增量緩存開(kāi)始");addDateFirm(v , time);}}private void addDateFirm(List<Firm> firms , Long time){if(firms != null && firms.size() > 0 ){for(Firm firm : firms){firmData.put(firm.getFirmId() , firm);}}firmDataTime = new Timestamp(time);}//全量緩存@Scheduled(cron = "0 0 0 1/1 * ? ")public void cacheAllFirm(){firmData = null;List<Firm> firms = firmRepo.findAll();ConcurrentHashMap<Integer , Firm> allFirmMap= new ConcurrentHashMap<>();for(Firm firm : firms){allFirmMap.put(firm.getFirmId() , firm);}firmData = allFirmMap;} }

定時(shí)任務(wù)多線程配置

import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.annotation.SchedulingConfigurer; import org.springframework.scheduling.config.ScheduledTaskRegistrar;import java.util.concurrent.Executor; import java.util.concurrent.Executors;/*** 沒(méi)有此配置,則schedule為單線程串行執(zhí)行*/ @Configuration @EnableScheduling public class ScheduleConfig implements SchedulingConfigurer {@Overridepublic void configureTasks(ScheduledTaskRegistrar taskRegistrar) {taskRegistrar.setScheduler(taskExecutor());}//配置線程池---觸發(fā)器和任務(wù)共用的@Bean(destroyMethod="shutdown")public Executor taskExecutor() {return Executors.newScheduledThreadPool(10);} }

實(shí)體類(lèi)

import lombok.Data; import lombok.experimental.Accessors;import javax.persistence.*; import java.io.Serializable;@Data @Entity @Table(name = "firm") public class Firm implements Serializable {@Id@GeneratedValue@Column(name = "firm_id")private Integer firmId;@Column(name = "firm_name")private String firmName;@Column(name = "create_time", insertable = false, updatable = false)private java.sql.Timestamp createTime;@Column(name = "update_time", insertable = false, updatable = false)private java.sql.Timestamp updateTime;}

JPA

import com.tjdami.zs.test.jpa.model.Firm; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query;import java.sql.Timestamp; import java.util.List; import java.util.Map;public interface FirmRepo extends JpaRepository<Firm, Integer>, JpaSpecificationExecutor<Firm> {List<Firm> findAllByUpdateTimeAfterOrCreateTimeAfter(Timestamp timea , Timestamp timeb);}

以上就是本期的全部?jī)?nèi)容了,操作數(shù)據(jù)庫(kù)的技術(shù)為JPA加哈伯奈特,換成mybatis或者jdbc也是一樣的簡(jiǎn)單哦,如果大家覺(jué)得有幫助一定記得動(dòng)動(dòng)小手點(diǎn)個(gè)贊。

總結(jié)

以上是生活随笔為你收集整理的JAVA数据缓存之内存缓存的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。