国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Redis詳解 - SpringBoot整合Redis,RedisTemplate和注解兩種方式的使

SexySix / 487人閱讀

摘要:和注解的方法返回值要一致刪除緩存在需要刪除緩存的方法上加注解,執行完這個方法之后會將中對應的記錄刪除。代表返回值,意思是當返回碼不等于時不緩存,也就是等于時才緩存。返回值特定值如果被設置了如果沒有被設置例子自動將對應到并且返回原來對應的。

本文主要講 Redis 的使用,如何與 SpringBoot 項目整合,如何使用注解方式和 RedisTemplate 方式實現緩存。最后會給一個用 Redis 實現分布式鎖,用在秒殺系統中的案例。

更多 Redis 的實際運用場景請關注開源項目 coderiver

項目地址:https://github.com/cachecats/...

一、NoSQL 概述 什么是 NoSQL ?

NoSQL(NoSQL = Not Only SQL ),意即“不僅僅是SQL”,泛指非關系型的數據庫。

為什么需要 NoSQL ?

隨著互聯網web2.0網站的興起,傳統的關系數據庫在應付web2.0網站,特別是超大規模和高并發的SNS類型的web2.0純動態網站已經顯得力不從心,暴露了很多難以克服的問題,而非關系型的數據庫則由于其本身的特點得到了非常迅速的發展。NoSQL數據庫的產生就是為了解決大規模數據集合多重數據種類帶來的挑戰,尤其是大數據應用難題。 -- 百度百科

NoSQL 數據庫的四大分類

鍵值(key-value)存儲

列存儲

文檔數據庫

圖形數據庫

分類 相關產品 典型應用 數據模型 優點 缺點
鍵值(key-value) Tokyo、 Cabinet/Tyrant、Redis、Voldemort、Berkeley DB 內容緩存,主要用于處理大量數據的高訪問負載 一系列鍵值對 快速查詢 存儲的數據缺少結構化
列存儲數據庫 Cassandra, HBase, Riak 分布式的文件系統 以列簇式存儲,將同一列數據存在一起 查找速度快,可擴展性強,更容易進行分布式擴展 功能相對局限
文檔數據庫 CouchDB, MongoDB Web應用(與Key-Value類似,value是結構化的) 一系列鍵值對 數據結構要求不嚴格 查詢性能不高,而且缺乏統一的查詢語法
圖形(Graph)數據庫 Neo4J, InfoGrid, Infinite Graph 社交網絡,推薦系統等。專注于構建關系圖譜 圖結構 利用圖結構相關算法 需要對整個圖做計算才能得出結果,不容易做分布式集群方案
NoSQL 的特點

易擴展

靈活的數據模型

大數據量,高性能

高可用

二、Redis 概述 Redis的應用場景

緩存

任務隊列

網站訪問統計

應用排行榜

數據過期處理

分布式集群架構中的 session 分離

Redis 安裝

網上有很多 Redis 的安裝教程,這里就不多說了,只說下 Docker 的安裝方法:

Docker 安裝運行 Redis

docker run -d -p 6379:6379 redis:4.0.8

如果以后想啟動 Redis 服務,打開命令行,輸入以下命令即可。

redis-server

使用前先引入依賴


    org.springframework.boot
    spring-boot-starter-data-redis
三、注解方式使用 Redis 緩存

使用緩存有兩個前置步驟

pom.xml 引入依賴


    org.springframework.boot
    spring-boot-starter-data-redis

在啟動類上加注解 @EnableCaching

@SpringBootApplication
@EnableCaching
public class SellApplication {
    public static void main(String[] args) {
        SpringApplication.run(SellApplication.class, args);
    }
}

常用的注解有以下幾個

@Cacheable

屬性如下圖

用于查詢和添加緩存,第一次查詢的時候返回該方法返回值,并向 Redis 服務器保存數據。

以后調用該方法先從 Redis 中查是否有數據,如果有直接返回 Redis 緩存的數據,而不執行方法里的代碼。如果沒有則正常執行方法體中的代碼。

value 或 cacheNames 屬性做鍵,key 屬性則可以看作為 value 的子鍵, 一個 value 可以有多個 key 組成不同值存在 Redis 服務器。

驗證了下,value 和 cacheNames 的作用是一樣的,都是標識主鍵。兩個屬性不能同時定義,只能定義一個,否則會報錯。

condition 和 unless 是條件,后面會講用法。其他的幾個屬性不常用,其實我也不知道怎么用…

@CachePut

更新 Redis 中對應鍵的值。屬性和 @Cacheable 相同

@CacheEvict

刪除 Redis 中對應鍵的值。

3.1 添加緩存

在需要加緩存的方法上添加注解 @Cacheable(cacheNames = "product", key = "123"),

cacheNameskey 都必須填,如果不填 key ,默認的 key 是當前的方法名,更新緩存時會因為方法名不同而更新失敗。

如在訂單列表上加緩存

    @RequestMapping(value = "/list", method = RequestMethod.GET)
    @Cacheable(cacheNames = "product", key = "123")
    public ResultVO list() {

        // 1.查詢所有上架商品
        List productInfoList = productInfoService.findUpAll();

        // 2.查詢類目(一次性查詢)
        //用 java8 的特性獲取到上架商品的所有類型
        List categoryTypes = productInfoList.stream().map(e -> e.getCategoryType()).collect(Collectors.toList());
        List productCategoryList = categoryService.findByCategoryTypeIn(categoryTypes);

        List productVOList = new ArrayList<>();
        //數據拼裝
        for (ProductCategory category : productCategoryList) {
            ProductVO productVO = new ProductVO();
            //屬性拷貝
            BeanUtils.copyProperties(category, productVO);
            //把類型匹配的商品添加進去
            List productInfoVOList = new ArrayList<>();
            for (ProductInfo productInfo : productInfoList) {
                if (productInfo.getCategoryType().equals(category.getCategoryType())) {
                    ProductInfoVO productInfoVO = new ProductInfoVO();
                    BeanUtils.copyProperties(productInfo, productInfoVO);
                    productInfoVOList.add(productInfoVO);
                }
            }
            productVO.setProductInfoVOList(productInfoVOList);
            productVOList.add(productVO);
        }

        return ResultVOUtils.success(productVOList);
    }

可能會報如下錯誤

對象未序列化。讓對象實現 Serializable 方法即可

@Data
public class ProductVO implements Serializable {
    
    private static final long serialVersionUID = 961235512220891746L;

    @JsonProperty("name")
    private String categoryName;

    @JsonProperty("type")
    private Integer categoryType;

    @JsonProperty("foods")
    private List productInfoVOList ;
}

生成唯一的 id 在 IDEA 里有一個插件:GenerateSerialVersionUID 比較方便。

重啟項目訪問訂單列表,在 rdm 里查看 Redis 緩存,有 product::123 說明緩存成功。

3.2 更新緩存

在需要更新緩存的方法上加注解: @CachePut(cacheNames = "prodcut", key = "123")

注意

cacheNameskey 要跟 @Cacheable() 里的一致,才會正確更新。

@CachePut()@Cacheable() 注解的方法返回值要一致

3.3 刪除緩存

在需要刪除緩存的方法上加注解:@CacheEvict(cacheNames = "prodcut", key = "123"),執行完這個方法之后會將 Redis 中對應的記錄刪除。

3.4 其他常用功能

cacheNames 也可以統一寫在類上面, @CacheConfig(cacheNames = "product") ,具體的方法上就不用寫啦。

@CacheConfig(cacheNames = "product")
public class BuyerOrderController {
    @PostMapping("/cancel")
    @CachePut(key = "456")
    public ResultVO cancel(@RequestParam("openid") String openid,
                           @RequestParam("orderId") String orderId){
        buyerService.cancelOrder(openid, orderId);
        return ResultVOUtils.success();
    }
}

Key 也可以動態設置為方法的參數

@GetMapping("/detail")
@Cacheable(cacheNames = "prodcut", key = "#openid")
public ResultVO detail(@RequestParam("openid") String openid,
                             @RequestParam("orderId") String orderId){
    OrderDTO orderDTO = buyerService.findOrderOne(openid, orderId);
    return ResultVOUtils.success(orderDTO);
}

如果參數是個對象,也可以設置對象的某個屬性為 key。比如其中一個參數是 user 對象,key 可以寫成 key="#user.id"

緩存還可以設置條件。

設置當 openid 的長度大于3時才緩存

@GetMapping("/detail")
@Cacheable(cacheNames = "prodcut", key = "#openid", condition = "#openid.length > 3")
public ResultVO detail(@RequestParam("openid") String openid,
                                 @RequestParam("orderId") String orderId){
    OrderDTO orderDTO = buyerService.findOrderOne(openid, orderId);
    return ResultVOUtils.success(orderDTO);
}

還可以指定 unless 即條件不成立時緩存。#result 代表返回值,意思是當返回碼不等于 0 時不緩存,也就是等于 0 時才緩存。

@GetMapping("/detail")
@Cacheable(cacheNames = "prodcut", key = "#openid", condition = "#openid.length > 3", unless = "#result.code != 0")
public ResultVO detail(@RequestParam("openid") String openid,
                                 @RequestParam("orderId") String orderId){
    OrderDTO orderDTO = buyerService.findOrderOne(openid, orderId);
    return ResultVOUtils.success(orderDTO);
}

四、RedisTemplate 使用 Redis 緩存

與使用注解方式不同,注解方式可以零配置,只需引入依賴并在啟動類上加上 @EnableCaching 注解就可以使用;而使用 RedisTemplate 方式麻煩些,需要做一些配置。

4.1 Redis 配置

第一步還是引入依賴和在啟動類上加上 @EnableCaching 注解。

然后在 application.yml 文件中配置 Redis

spring:
  redis:
    port: 6379
    database: 0
    host: 127.0.0.1
    password:
    jedis:
      pool:
        max-active: 8
        max-wait: -1ms
        max-idle: 8
        min-idle: 0
    timeout: 5000ms

然后寫個 RedisConfig.java 配置類

package com.solo.coderiver.user.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
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.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;

import java.net.UnknownHostException;


@Configuration
public class RedisConfig {

    @Bean
    @ConditionalOnMissingBean(name = "redisTemplate")
    public RedisTemplate redisTemplate(
            RedisConnectionFactory redisConnectionFactory)
            throws UnknownHostException {

        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);

        RedisTemplate template = new RedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);
        template.setKeySerializer(jackson2JsonRedisSerializer);
        template.setValueSerializer(jackson2JsonRedisSerializer);
        template.setHashKeySerializer(jackson2JsonRedisSerializer);
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();
        return template;
    }

    @Bean
    @ConditionalOnMissingBean(StringRedisTemplate.class)
    public StringRedisTemplate stringRedisTemplate(
            RedisConnectionFactory redisConnectionFactory)
            throws UnknownHostException {
        StringRedisTemplate template = new StringRedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }
}

Redis 的配置就完成了。

4.2 Redis 的數據結構類型

Redis 可以存儲鍵與5種不同數據結構類型之間的映射,這5種數據結構類型分別為String(字符串)、List(列表)、Set(集合)、Hash(散列)和 Zset(有序集合)。

下面來對這5種數據結構類型作簡單的介紹:

結構類型 結構存儲的值 結構的讀寫能力
String 可以是字符串、整數或者浮點數 對整個字符串或者字符串的其中一部分執行操作;對象和浮點數執行自增(increment)或者自減(decrement)
List 一個鏈表,鏈表上的每個節點都包含了一個字符串 從鏈表的兩端推入或者彈出元素;根據偏移量對鏈表進行修剪(trim);讀取單個或者多個元素;根據值來查找或者移除元素
Set 包含字符串的無序收集器(unorderedcollection),并且被包含的每個字符串都是獨一無二的、各不相同 添加、獲取、移除單個元素;檢查一個元素是否存在于某個集合中;計算交集、并集、差集;從集合里賣弄隨機獲取元素
Hash 包含鍵值對的無序散列表 添加、獲取、移除單個鍵值對;獲取所有鍵值對
Zset 字符串成員(member)與浮點數分值(score)之間的有序映射,元素的排列順序由分值的大小決定 添加、獲取、刪除單個元素;根據分值范圍(range)或者成員來獲取元素
4.3 StringRedisTemplate 與 RedisTemplate

RedisTemplate 對五種數據結構分別定義了操作

redisTemplate.opsForValue();

操作字符串

redisTemplate.opsForHash();

操作hash

redisTemplate.opsForList();

操作list

redisTemplate.opsForSet();

操作set

redisTemplate.opsForZSet();

操作有序set

如果操作字符串的話,建議用 StringRedisTemplate

StringRedisTemplate 與 RedisTemplate 的區別

StringRedisTemplate 繼承了 RedisTemplate。

RedisTemplate 是一個泛型類,而 StringRedisTemplate 則不是。

StringRedisTemplate 只能對 key=String,value=String 的鍵值對進行操作,RedisTemplate 可以對任何類型的 key-value 鍵值對操作。

他們各自序列化的方式不同,但最終都是得到了一個字節數組,殊途同歸,StringRedisTemplate 使用的是 StringRedisSerializer 類;RedisTemplate 使用的是 JdkSerializationRedisSerializer 類。反序列化,則是一個得到 String,一個得到 Object

兩者的數據是不共通的,StringRedisTemplate 只能管理 StringRedisTemplate 里面的數據,RedisTemplate 只能管理 RedisTemplate中 的數據。

4.4 項目中使用

在需要使用 Redis 的地方,用 @Autowired 注入進來

@Autowired
RedisTemplate redisTemplate;
 
@Autowired
StringRedisTemplate stringRedisTemplate;

由于項目中暫時僅用到了 StringRedisTemplate 與 RedisTemplate 的 Hash 結構,StringRedisTemplate 比較簡單就不貼代碼了,下面僅對操作 Hash 進行舉例。

關于 RedisTemplate 的詳細用法,有一篇文章已經講的很細很好了,我覺得沒必要再去寫了。傳送門

用 RedisTemplate 操作 Hash
package com.solo.coderiver.user.service.impl;

import com.solo.coderiver.user.dataobject.UserLike;
import com.solo.coderiver.user.dto.LikedCountDTO;
import com.solo.coderiver.user.enums.LikedStatusEnum;
import com.solo.coderiver.user.service.LikedService;
import com.solo.coderiver.user.service.RedisService;
import com.solo.coderiver.user.utils.RedisKeyUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Service
@Slf4j
public class RedisServiceImpl implements RedisService {

    @Autowired
    RedisTemplate redisTemplate;

    @Autowired
    LikedService likedService;

    @Override
    public void saveLiked2Redis(String likedUserId, String likedPostId) {
        String key = RedisKeyUtils.getLikedKey(likedUserId, likedPostId);
        redisTemplate.opsForHash().put(RedisKeyUtils.MAP_KEY_USER_LIKED, key, LikedStatusEnum.LIKE.getCode());
    }

    @Override
    public void unlikeFromRedis(String likedUserId, String likedPostId) {
        String key = RedisKeyUtils.getLikedKey(likedUserId, likedPostId);
        redisTemplate.opsForHash().put(RedisKeyUtils.MAP_KEY_USER_LIKED, key, LikedStatusEnum.UNLIKE.getCode());
    }

    @Override
    public void deleteLikedFromRedis(String likedUserId, String likedPostId) {
        String key = RedisKeyUtils.getLikedKey(likedUserId, likedPostId);
        redisTemplate.opsForHash().delete(RedisKeyUtils.MAP_KEY_USER_LIKED, key);
    }

    @Override
    public void incrementLikedCount(String likedUserId) {
        redisTemplate.opsForHash().increment(RedisKeyUtils.MAP_KEY_USER_LIKED_COUNT, likedUserId, 1);
    }

    @Override
    public void decrementLikedCount(String likedUserId) {
        redisTemplate.opsForHash().increment(RedisKeyUtils.MAP_KEY_USER_LIKED_COUNT, likedUserId, -1);
    }

    @Override
    public List getLikedDataFromRedis() {
        Cursor> cursor = redisTemplate.opsForHash().scan(RedisKeyUtils.MAP_KEY_USER_LIKED, ScanOptions.NONE);
        List list = new ArrayList<>();
        while (cursor.hasNext()) {
            Map.Entry entry = cursor.next();
            String key = (String) entry.getKey();
            //分離出 likedUserId,likedPostId
            String[] split = key.split("::");
            String likedUserId = split[0];
            String likedPostId = split[1];
            Integer value = (Integer) entry.getValue();

            //組裝成 UserLike 對象
            UserLike userLike = new UserLike(likedUserId, likedPostId, value);
            list.add(userLike);

            //存到 list 后從 Redis 中刪除
            redisTemplate.opsForHash().delete(RedisKeyUtils.MAP_KEY_USER_LIKED, key);
        }

        return list;
    }

    @Override
    public List getLikedCountFromRedis() {
        Cursor> cursor = redisTemplate.opsForHash().scan(RedisKeyUtils.MAP_KEY_USER_LIKED_COUNT, ScanOptions.NONE);
        List list = new ArrayList<>();
        while (cursor.hasNext()) {
            Map.Entry map = cursor.next();
            //將點贊數量存儲在 LikedCountDT
            String key = (String) map.getKey();
            LikedCountDTO dto = new LikedCountDTO(key, (Integer) map.getValue());
            list.add(dto);
            //從Redis中刪除這條記錄
            redisTemplate.opsForHash().delete(RedisKeyUtils.MAP_KEY_USER_LIKED_COUNT, key);
        }
        return list;
    }
}
五、Redis 實現分布式鎖

講完了基礎操作,再說個實戰運用,用Redis 實現分布式鎖 。

實現分布式鎖之前先看兩個 Redis 命令:

SETNX

key設置值為value,如果key不存在,這種情況下等同SET命令。 當key存在時,什么也不做。SETNX是”SET if Not eXists”的簡寫。

返回值

Integer reply, 特定值:

1 如果key被設置了

0 如果key沒有被設置

例子

redis> SETNX mykey "Hello"
(integer) 1
redis> SETNX mykey "World"
(integer) 0
redis> GET mykey
"Hello"
redis> 

GETSET

自動將key對應到value并且返回原來key對應的value。如果key存在但是對應的value不是字符串,就返回錯誤。

設計模式

GETSET可以和INCR一起使用實現支持重置的計數功能。舉個例子:每當有事件發生的時候,一段程序都會調用INCR給key mycounter加1,但是有時我們需要獲取計數器的值,并且自動將其重置為0。這可以通過GETSET mycounter “0”來實現:

INCR mycounter
GETSET mycounter "0"
GET mycounter

返回值

bulk-string-reply: 返回之前的舊值,如果之前Key不存在將返回nil

例子

redis> INCR mycounter
(integer) 1
redis> GETSET mycounter "0"
"1"
redis> GET mycounter
"0"
redis>

這兩個命令在 java 中對應為 setIfAbsentgetAndSet

分布式鎖的實現:

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

@Component
@Slf4j
public class RedisLock {

    @Autowired
    StringRedisTemplate redisTemplate;

    /**
     * 加鎖
     * @param key
     * @param value 當前時間 + 超時時間
     * @return
     */
    public boolean lock(String key, String value){
        if (redisTemplate.opsForValue().setIfAbsent(key, value)){
            return true;
        }

        //解決死鎖,且當多個線程同時來時,只會讓一個線程拿到鎖
        String currentValue = redisTemplate.opsForValue().get(key);
        //如果過期
        if (!StringUtils.isEmpty(currentValue) &&
                Long.parseLong(currentValue) < System.currentTimeMillis()){
            //獲取上一個鎖的時間
            String oldValue = redisTemplate.opsForValue().getAndSet(key, value);
            if (StringUtils.isEmpty(oldValue) && oldValue.equals(currentValue)){
                return true;
            }
        }

        return false;
    }

    /**
     * 解鎖
     * @param key
     * @param value
     */
    public void unlock(String key, String value){

        try {
            String currentValue = redisTemplate.opsForValue().get(key);
            if (!StringUtils.isEmpty(currentValue) && currentValue.equals(value)){
                redisTemplate.opsForValue().getOperations().delete(key);
            }
        }catch (Exception e){
            log.error("【redis鎖】解鎖失敗, {}", e);
        }
    }
}

使用:

/**
 * 模擬秒殺
 */
public class SecKillService {

    @Autowired
    RedisLock redisLock;

    //超時時間10s
    private static final int TIMEOUT = 10 * 1000;

    public void secKill(String productId){
        long time = System.currentTimeMillis() + TIMEOUT;
        //加鎖
        if (!redisLock.lock(productId, String.valueOf(time))){
            throw new SellException(101, "人太多了,等會兒再試吧~");
        }

        //具體的秒殺邏輯

        //解鎖
        redisLock.unlock(productId, String.valueOf(time));
    }
}

更多 Redis 的具體使用場景請關注開源項目 CodeRiver,致力于打造全平臺型全棧精品開源項目。

coderiver 中文名 河碼,是一個為程序員和設計師提供項目協作的平臺。無論你是前端、后端、移動端開發人員,或是設計師、產品經理,都可以在平臺上發布項目,與志同道合的小伙伴一起協作完成項目。

coderiver河碼 類似程序員客棧,但主要目的是方便各細分領域人才之間技術交流,共同成長,多人協作完成項目。暫不涉及金錢交易。

計劃做成包含 pc端(Vue、React)、移動H5(Vue、React)、ReactNative混合開發、Android原生、微信小程序、java后端的全平臺型全棧項目,歡迎關注。

項目地址:https://github.com/cachecats/...

您的鼓勵是我前行最大的動力,歡迎點贊,歡迎送小星星? ~

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/72271.html

相關文章

  • springboot 整合redis

    摘要:與整合默認使用的是,相較于,是一個可伸縮的,線程安全的客戶端。在處理高并發方面有更多的優勢。使用依賴主要需要的依賴為配置配置使用與整合可以在不更改現有代碼邏輯的基礎上,通過增加注解的方式,實現緩存。 springboot2.0 與redis整合默認使用的是Lettuce,相較于jedis,lettuce 是一個可伸縮的,線程安全的redis客戶端。在處理高并發方面有更多的優勢。 Red...

    elarity 評論0 收藏0
  • springboot系列】springboot整合獨立模塊 redis 做緩存

    摘要:至此,已完成整合獨立模塊做緩存詳情請看地址相關文章系列整合獨立模塊 項目github地址:https://github.com/5-Ason/aso...具體可看 ./db/db-redis 和 ./db/db-cache 兩個模塊 // TODO 在整合redis之前需要先本地配置好redis環境,遲點有時間補一下linux下下載安裝配置redis 本文主要實現的是對數據操作進行獨立...

    qianfeng 評論0 收藏0
  • springboot系列】springboot整合獨立模塊 redis 做緩存

    摘要:至此,已完成整合獨立模塊做緩存詳情請看地址相關文章系列整合獨立模塊 項目github地址:https://github.com/5-Ason/aso...具體可看 ./db/db-redis 和 ./db/db-cache 兩個模塊 // TODO 在整合redis之前需要先本地配置好redis環境,遲點有時間補一下linux下下載安裝配置redis 本文主要實現的是對數據操作進行獨立...

    Jokcy 評論0 收藏0

發表評論

0條評論

SexySix

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<