redis-SpringBoot(21)

来源:https://www.cnblogs.com/liwenruo/archive/2022/08/11/16575571.html
-Advertisement-
Play Games

Redis是大規模互聯網應用常用的記憶體高速緩存資料庫,它的讀寫速度非常快,據官方 Bench-mark的數據,它讀的速度能到11萬次/秒,寫的速度是8.1萬次/秒。 1. 認識Spring Cache 在很多應用場景中通常是獲取前後相同或更新不頻繁的數據,比如訪問產品信息數據、網頁數據。如果沒有使用 ...


  Redis是大規模互聯網應用常用的記憶體高速緩存資料庫,它的讀寫速度非常快,據官方 Bench-mark的數據,它讀的速度能到11萬次/秒,寫的速度是8.1萬次/秒。

1. 認識Spring Cache

  在很多應用場景中通常是獲取前後相同或更新不頻繁的數據,比如訪問產品信息數據、網頁數據。如果沒有使用緩存,則訪問每次需要重覆請求資料庫,這會導致大部分時間都耗費在資料庫查詢和方法調用上,因為資料庫進行I/O操作非常耗費時間,這時就可以利用Spring Cache來解決。

  Spring Cache是Spring提供的一整套緩存解決方案。它本身並不提供緩存實現,而是提供統 一的介面和代碼規範、配置、註解等,以便整合各種Cache方案,使用戶不用關心Cache的細節。

  Spring支持“透明”地嚮應用程式添加緩存,將緩存應用於方法,在方法執行前檢查緩存中是否有可用的數據。這樣可以減少方法執行的次數,同時提高響應的速度。緩存的應用方式“透明”, 不會對調用者造成任何干擾。只要通過註解@EnableCaching啟用了緩存支持,Spring Boot就會自動處理好緩存的基礎配置。

  Spring Cache作用在方法上。當調用一個緩存方法時,會把該方法參數和返回結果作為一個 “鍵值對”(key/value )存放在緩存中,下次用同樣的參數來調用該方法時將不再執行該方法,而是直接從緩存中獲取結果進行返回。所以在使用Spring Cache 時,要保證在緩存的方法和方法參數相同時返回相同的結果。

  1.1 聲明式緩存註解

  Spring Boot提供的聲明式緩存(cache)註解,見表11-1。

  

圖 11-1

  1.@EnableCaching

  標註在入口類上,用於開啟緩存。

  2.@Cacheable

  可以作用在類和方法上,以鍵值對的方式緩存類或方法的返回值。鍵可以有預設策略和自定義策略。

  @Cacheable註解會先查詢是否己經有緩存,如果己有則會使用緩存,如果沒有則會執行方法併進行緩存。

  @Cacheabfe 可以指定 3 個屬性----- value、key 和 condition。

    • value :緩存的名稱,在Spring配置文件中定義,必須指定至少一個。如, @Cacheable(value= "cache1" )、@Cacheable(value={ "cache1" , "cache2n }。
    • key:緩存的key可以為空,如果自定義key,則要按照SpEL表達式編寫。可以自動按照方法的參數組合。如,@Cacheable(value= "cache1",key= "#id” )
    • condition:緩存的條件可以為空,如果自定義condition,則使用SpEL表達式輻寫,以返 回true或false值,只有返回true才進行緩存。如,@Cacheable(value= “cache1" ,condition= "#id.length()>2" )。

  @Cacheable註解的使用方法見以下代碼:

@Override
@Cacheable(value = "emp",key = "targetClass + methodName + #p0")
public List<Card> getCardList() {
    return cardRepository.findAll();
}

代碼解釋如下。

  • value是必需的,它指定了緩存存放的位置。
  • key使用的是SpEL表達式。
  • User實體類一定要實現序列化,否則會報“java.io.NotSerializableException”異常。序 列化可以繼承 Serializable,如 public class User implements Serializable。

 3. @CachePut

  @CachePut標註的方法在執行前不檢查緩存中是否存在之前執行過的結果,而是每次都會執行該方法,並將執行結果以鍵值對的形式存入指定的緩存中。和@Cacheable不同的是, @CachePut每次都會觸發真實方法的調用,比如用戶更新緩存數據。

  需要註意的是,該註解的value和key必須與要更新的緩存相同,即與@Cacheable 相同。 具體見下麵兩段代碼:

@Override
@CachePut(value = "usr",key = "targetClass + #p0")
public Book update(Book book) {
    return null;
}

@Override
@Cacheable(value = "usr",key = "targetClass + #p0")
public Book save(Book book) {
    return null;
}

  4. @CacheEvict

  @CacheEvict用來標註需要清除緩存元素的方法或類。該註解用於觸發緩存的清除操作。其屬性有value、key、condition、allEntries 和 beforeInvocation。可以用這些屬性來指定清除的條件。使用方法如下:

@Override
@Cacheable(value = "usr",key = "#p0.id")
public Book save(Book book) {
    return null;
}

@Override
@CacheEvict(value = "usr",key = "#id")
public void delete(int id) {
}

@Override
@CacheEvict(value = "accountCache",allEntries = true)
public void deleteAll() {

}

@Override
@CacheEvict(value = "accountCache",beforeInvocation = true)
public void deleteAll() {

}

  5. @Caching

  註解@Caching用來組合多個註解標簽,有3個屬性:cacheable、put 和 evict,用於指定 @Cacheable、@CachePut 和 @CacheEvict。使用方法如下:

@Override
@Caching(cacheable = {@Cacheable(value = "usr",key = "#p0"),},
         put = {@CachePut(value = "usr",key = "#p0"),},
         evict = {@CacheEvict(value = "usr",key = "#p0"),})
public Book save(Book book) {
    return null;
}

  1.2 實例:用Spring Cache進行緩存管理

  本實例展示Spring Cache是如何使用簡單緩存(SIMPLE方式)進行緩存管理的。

  (1)添加依賴

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
    <version>2.7.2</version>
</dependency>

  (2)配置緩存管理器

  在application.yml文件中配置目標緩存管理器,支持Ehcache、Generic、Redis、 Jcache 等。這裡使用 SIMPLE 方式 "spring: cache: type: SIMPLE”。

  (3)開啟緩存功能

  在入口類添加註解@EnableCaching,開啟緩存功能。

  (4)在服務實現里編寫緩存業務邏輯:

@Service
public class BookServiceImpl implements BookService{
    @Autowired
    private BookDao bookDao;
    @Override
    public Book getById(Integer id) {
        return bookDao.getById(id);
    }
    
    @Override
    public void insert(Book book) {
        bookDao.insert(book);
    }

    @Override
    @CachePut(value = "usr",key = "targetClass + #p0")
    public Book update(Book book) {
        return null;
    }

    @Override
    @Caching(cacheable = {@Cacheable(value = "usr",key = "#p0"),},
            put = {@CachePut(value = "usr",key = "#p0"),},
            evict = {@CacheEvict(value = "usr",key = "#p0"),})
    public Book save(Book book) {
        return null;
    }

    @Override
    @CacheEvict(value = "usr",key = "#id")
    public void delete(int id) {
    }

    @Override
    @CacheEvict(value = "accountCache",allEntries = true)
    public void deleteAll() {

    }
}

  上述代碼可以看出,查找用戶的方法使用了註解@Cacheable來開啟緩存。修改和添加方法使用了註解@CachePut。它是先處理方法,然後把結果進行緩存的。要想刪除數據,則需要使用註解@CacheEvict來清空緩存。

  (5)控制器里調用緩存服務

查看代碼
 @EnableCaching
@Controller
public class BookController {
    @Autowired
    private BookService bookService;
    int id = 0;

    @RequestMapping("/book")
    public String insert(){
        Book book = new Book();
        book.setUsername("拉行啊");
        book.setPassword("123");
        String jsonObject = JSON.toJSONString(book);
        System.out.println(jsonObject);
        book.setJson(jsonObject);
        bookService.insert(book);
        id = book.getId();
        return book.toString();
    }
    @RequestMapping(value = "/get",method = RequestMethod.GET,produces = "application/json")
    public Book get(){
        Book book = new Book();
        book.setUsername("拉行啊");
        book.setPassword("123");
        return book;
    }
    @RequestMapping(value = "/put")
    public String put(@RequestParam("upload")MultipartFile file, RedirectAttributes redirectAttributes){
        Date date = new Date();
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
        String nyr = dateFormat.format(date);
        if (file.getOriginalFilename().endsWith(".jpg")||file.getOriginalFilename().endsWith(".png")||
                file.getOriginalFilename().endsWith(".git")){
            try {
                byte[] bytes = file.getBytes();
                String s = nyr+Math.random()+file.getOriginalFilename();
                Path path = Paths.get("./"+s);
                Files.write(path, bytes);
                return "success";
            } catch (Throwable e) {
                e.printStackTrace();
            }
        }else {
            return "格式不支持";
        }
        return "error";
    }
    @RequestMapping(value = "/test")
    public String test(Model model) throws Exception{
        Book book = new Book();
        book.setPassword("123");
        model.addAttribute("book",book);
        return "test";
    }
}

   1.3 整合 Ehcache

  Spring Boot支持多種不同的緩存產品。在預設情況下使用的是簡單緩存,不建議在正式環境中使用。我們可以配置一些更加強大的緩存,比如Ehcache。Ehcache是一種廣泛使用的開源Java分散式緩存,它具有記憶體和磁碟存儲、緩存載入器、緩存擴展、緩存異常處理、GZIP緩存、Servlet過濾器,以及支持REST和SOAP API等特點。

@Service
@CacheConfig(cacheNames = {"userCache"})
public class BookServiceImpl implements BookService{
    @Autowired
    private BookDao bookDao;
    
    @Override
    @Cacheable(value = "usr",key = "targetClass + #p0")
    public Page<Book> findAll() {
        return bookDao.findAll();
    }
}

  1.4 整合 Caffeine

  Caffeine是使用Java 8對Guava緩存的重寫版本。它基於LRU演算法實現,支持多種緩存過期策略。要使用它,需要在pom.xml文件中增加Caffeine依賴,這樣Spring Boot就會自動用 Caffeine替換預設的簡單緩存。

  增加Caffeine依賴的代碼如下:

<dependency>
    <groupId>com.github.ben-manes.caffeine</groupId>
    <artifactId>caffeine</artifactId>
</dependency>

  然後配置參數,見以下代碼:

spring:
  cache:
    type: caffeine
    cache-names: myCaffeine
    caffeine:
      spec: maximumSize=1,expireAfterAccess=5s

代碼解釋如下。

  • cache.type:指定使用哪個緩存供應商。
  • cache.cache-names:在啟動時創建緩存名稱(即前面的cacheNames )。如果有多個名稱,則用逗號進行分隔。
  • cache.caffeine.spec:這是 Caffeine 緩存的專用配置。
  • maximumSize=1:最大緩存數量。如果超出最大緩存數量,則保留後進(最新)的,最開始的緩存會被清除。
  • expireAfterAccess=5s:緩存5s,即緩存在5 s之內沒有被使用,就會被清除,在預設情況下,緩存的數據會一直保存在記憶體中。有些數據可能用一次後很長時間都不會再月,這樣會有大量無用的數據長時間占用記憶體,我們可以通過配置及時清除不需要的緩存。

2. 認識Redis

  2.1 對比 Redis 與 Memcached

  Cache可以和Redis一起用,Spring Boot支持把Cache存到Redis里。如果是單伺服器, 則用Cache、Ehcache或Caffeine,性能更高也能滿足需求。如果擁有伺服器集群,則可以使用 Redis,這樣性能更高。

  1. Redis

  Redis是目前使用最廣泛的記憶體數據存儲系統之一。它支持更豐富的數據結構,支持數據持久化、事務、HA (高可用High Available)雙機集群系統、主從庫。

  Redis是key-value存儲系統。它支持的value類型包括String、List、Set、Zset (有序集合)和Hash。這些數據類型都支持push/pop、add/remove,以及取交集、並集、差集或更豐富的操作,而且這些操作都是原子性的。在此基礎上,Redis支持各種不同方式的排序和演算法。

  Redis會周期性地把更新後的數據寫入磁碟,或把修改操作寫入追加的記錄文件中(RDB和 AOF兩種方式),並且在此基礎上實現了 master-slave (主從)同步。機器重啟後,能通過持久化數據自動重建記憶體。如果使用Redis作為Cache,則機器宕機後熱點數據不會丟失。

  豐富的數據結構加上Redis兼具緩存系統和資料庫等特性,使得Redis擁有更加豐富的應用場景。

  Redis可能會導致的問題:

    • 緩存和資料庫雙寫一致性問題。
    • 緩存雪崩問題。
    • 緩存擊穿問題。
    • 緩存的併發競爭問題。

  Redis為什麼快:

    • 純記憶體操作。
    • 單線程操作,避免了頻繁的上下文切換。
    • 採用了非阻塞I/O多路復用機制。

  2. Memcached

  Memcached的協議簡單,它基於Libevent的事件處理,內置記憶體存儲方式。Memcached 的分散式不互相通信,即各個Memcached不會互相通信以共用信息,分佈策略由客戶端實現。它不會對數據進行持久化,重啟Memcached、重啟操作系統都會導致全部數據消失。

  Memcached常見的應用場景一存儲一些讀取頻繁但更新較少的數據,如靜態網頁、系統配置及規則數據、活躍用戶的基本數據和個性化定製數據、實時統計信息等。

  3. 比較 Redis 與 Memcached

  (1)關註度。

    近年來,Redis越來越火熱,人們對Redis的關註度越來越高;對 Memcached關註度比較平穩,且有下降的趨勢。

  (2)性能。

    兩者的性能都比較高。

  (3)數據類型。

    Memcached的數據結構單一。

    Redis非常豐富。

  (4)記憶體大小。

    Redis在2.0版本後增加了自己的VM特性,突破物理記憶體的限制。

    Memcached可以修改最大可用記憶體的大小來管理記憶體,採用LRU演算法.

  (5)可用性。

    Redis依賴客戶端來實現分散式讀寫,在主從複製時,每次從節點重新連接主節點都要依賴整個快照,無增量複製。Redis不支持自動分片(sharding)。如果要實現分片功能,則需要依賴程式設定一致的散列(hash)機制。

    Memcached採用成熟的hash或環狀的演算法,來解決單點故障引起的抖動問題,其本身沒有數據冗餘機制。

  (6)持久化。

    Redis依賴快照、AOF進行持久化。但AOF在增強可靠性的同時,對性能也有所影響。

    Memcached不支持持久化,通常用來做緩存,以提升性能。

  (7)value數據大小。

    Redis的value的最大限制是1GB。

    Memcached只能保存1MB以內的數據。

  (8)數據一致性(事務支持)。

    Memcached在併發場景下用CAS保證一致性。

    Redis對事務支持比較弱,只能保證事務中的每個操作連續執行。

  (9)應用場景。

    Redis:適合數據量較少、性能操作和運算要求高的場景。

    Memcached:適合提升性能的場景。適合讀多與少,如果數據量比較大,則可以採用分片的方式來解決。

  2.2 Redis的適用場景

  1. 高併發的讀寫

    Redis特別適合將方法的運行結果放入緩存,以便後續在請求方法時直接去緩存中讀取。對執行耗時,且結果不頻繁變動的SQL查詢的支持極好。

    在高併發的情況下,應盡暈避免請求直接訪問資料庫,這時可以使用Redis進行緩衝操作,讓請求先訪問Redis。

  1. 計數器

    電商網站(APP)商品的瀏覽量、視頻網站(APP)視頻的播放數等數據都會被統計,以便用於運營或產品分析。為了保證數據實時生效,每次瀏覽都得+1,這會導致非常高的併發量。這時可以用Redis提供的incr命令來實現計數器功能,這一切在記憶體中操作,所以性能非常好,非常適用於這些計數場景。

  1. 排行榜

    可以利用Redis提供的有序集合數據類,實現各種複雜的排行榜應用。如京東、淘寶的銷量榜單,商品按時間、銷量排行等。

  1. 分散式會話

    在集群模式下,一般都會搭建以Redis等記憶體資料庫為中心的Session (會活)服務,它不再由容器管理,而是由Session服務及記憶體資料庫管理。

  1. 互動場景

    使用Redis提供的散列、集合等數據結構,可以很方便地實現網站(APP)中的點贊、踩、關註共同好友等社交場景的基本功能。

  1. 最新列表

    Redis可以通過LPUSH在列表頭部插入一個內容ID作為關鍵字,LTRIM可用來限制列表的數量,這樣列表永遠為N個ID,無須查詢最新的列表,直接根據ID查找対應的內容即可。

3. Redis的數據類型

  Redis有5種數據類型,見表11-2。

  

表 11-2

  1. 字元串(string)

    Redis字元串可以包含任意類型的數據、字元、整數、浮點數等。

    一個字元串類型的值的容量有512MB,代表能存儲最大512MB的內容。

    可以使用INCR (DECR、INCRBY)命令來把字元串當作原子計敬器使用。

    使用APPEND命令在字元串後添加內容。

    應用場景:計數器。

  1. 列表(list)

    Redis列表是簡單的字元串列表,按照插入順序排序。可以通過LPUSH、RPUSH命令添加一個元素到列表的頭部或尾部。

    一個列表最多可以包含以”232-1“(4294967295)個元素。

    應用場景:取最新N個數據的操作、消息隊列、刪除與過濾、實時分析正在發生的情況,數據統計與防止垃圾郵件(結合Set )。

  1. 集合(set)

    Redis集合是一個無序的、不允許相同成員存在的字元串合集。

    支持一些伺服器端的命令從現有的集合出發去進行集合運算,如合併(並集:union)、求交(交集intersection)、差集,找出不同元素的操作(共同好友、二度好友)。

    應用場景:Unique操作,可以獲取某段時間內所有數據“排重值”,比如用於共同好友、二度好友、統計獨立IP、好友推薦等。

  1. 散列(hash )

    Redis hash是字元串欄位和字元串值之間的映射,主要用來表示對象,也能夠存儲許多元素。

    應用場景:存儲、讀取、修改用戶屬性。

  1. 有序集合(sorted set、zset)

    Redis有序集合和Redis集合類似,是不包含相同字元串的合集。每個有序集合的成員都關聯著一個評分,這個評分用於把有序集合中的成員按最低分到最高分排列(排行榜應用,取TOP N 操作)。

    使用有序集合,可以非常快捷地完成添加、刪除和更新元素的操作。元素是在插入時就排好序 的,所以很快地通過評分(score )或位次(position )獲得一個範圍的元素。

    應用場景:排行榜應用、取TOP N、需要精準設定過期時間的應用(時間戳作為Score)、帶有權重的元素(游戲用戶得分排行榜)、過期項目處理、按照時間排序等。

4. 用RedisTemplate操作Redis的五種數據類型

  4.1 認識opsFor方法

Spring封裝了 RedisTemplate來操作Redis,它支持所有的Redis原生的API,在 RedisTemplate中定義了對5種數據結構的操作方法。

    • opsForValueQ:操作字元串。
    • opsForHashO:操作散列。
    • opsForList():操作列表。
    • opsForSet():操作集合。
    • opsForZSetO:操作有序集合。

下麵通過實例來理解和應用這些方法。這裡需要特別註意的是,運行上述方法後要對數據進行清空操作,否則多次運行會導致數據重覆操作。

4.2 操作字元串

  字元串(string )是Redis最基本的類型。string的一個“key”對應一個"value”,即key-value 鍵值對。string是二進位安全的,可以存儲任何數據(比如圖片或序列化的對象)。值最大能存儲512MB的數據。一般用於一些複雜的計數功能的緩存。RedisTemplate提供以下操作string的方法。

  (1)set void set(K key, V value);get V get(Object key)

@SpringBootTest
class RedisApplicationTests {
    @Autowired
    private RedisTemplate redisTemplate;
    @Test
    void contextLoads() {
        redisTemplate.opsForValue().set("hello", "world");
        redisTemplate.opsForValue().set("staing","somewhere");
        Object s = redisTemplate.opsForValue().get("hello");
        Object s2 = redisTemplate.opsForValue().get("staing");
        System.out.println(s);
        System.out.println(s2);
    }
}

  (2)set void set(K key, V value, long timeout, TimeUnit unit)

  以下代碼設置3 s失效。3 s之內查詢有結果,3 s之後查詢則返回為null。具體用法見以下代碼:

@SpringBootTest
class RedisApplicationTests {
    @Autowired
    private RedisTemplate redisTemplate;
    @Test
    void String(){
        redisTemplate.opsForValue().set("hello", "world",3, TimeUnit.SECONDS);
        try {
            Object s = redisTemplate.opsForValue().get("hello");
            System.out.println(s);
            Thread.currentThread().sleep(2000);
            s = redisTemplate.opsForValue().get("hello");
            System.out.println(s);
            Thread.currentThread().sleep(2000);
            s = redisTemplate.opsForValue().get("hello");
            System.out.println(s);
            Thread.currentThread().sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

TimeUnit是java.util.concurrent包下麵的一個類,表示給定單元粒度的時間段,常用的顆粒度有:

  • 小時(TimeUnit.HOURS )
  • 分鐘(TimeUnit.MINUTES ) 
  • 秒(TimeUnit.SECONDS ) 
  • 毫秒(TimeUnit.MILLISECONDS ) 

  (3)set void set(K key, V value, long offset)

  給定key所存儲的字元串值,從偏移量 offset開始。具體用法見以下代碼:

@SpringBootTest
class RedisApplicationTests {
    @Autowired
    private RedisTemplate redisTemplate;
    @Test
    void test() {
        redisTemplate.opsForValue().set("key", "hello world",6);
        System.out.println(redisTemplate.opsForValue().get("key"));
    }
}

  運行測試,輸出如下結果:

  hello

  (4)getAndSet V getAndSet(K key, V value)

  設置鍵的字元串值,並返回其舊值。具體用法見以下代碼:

@SpringBootTest
class RedisApplicationTests {
    @Autowired
    private RedisTemplate redisTemplate;
    @Test
    void test() {
        redisTemplate.opsForValue().set("hello", "world");
        System.out.println(redisTemplate.opsForValue().getAndSet("hello", "hey"));
        System.out.println(redisTemplate.opsForValue().get("hello"));
    }
}

  運行測試,輸出如下結果:

  world

  hey

  (5)append Integer append(K key, String value)

  如果key已經存在,並且是一個字元串,則該命令將該值追加到字元串的末尾。如果key不存在,則它將被創建並設置為空字元串,因此append在這種特殊情況下類似於set。用法見以下代碼:

@SpringBootTest
class RedisApplicationTests {
    @Autowired
    private RedisTemplate<String,String> redisTemplate;
    @Test
    void test() {
        redisTemplate.opsForValue().append("hello", "hello");
        System.out.println(redisTemplate.opsForValue().get("hello"));
        redisTemplate.opsForValue().append("hello", "world");
        System.out.println(redisTemplate.opsForValue().get("hello"));
    }
}

  運行測試,輸出如下結果:

  hello

  helloworld   

  這裡一定要註意反序列化配置,否則會報借。

  (6)size Long size(K key)

  返回key所對應的value值的長度,見以下代碼:

@SpringBootTest
class RedisApplicationTests {
    @Autowired
    private RedisTemplate redisTemplate;
    @Test
    void test() {
        redisTemplate.opsForValue().set("key", "1");
        System.out.println(redisTemplate.opsForValue().size("key"));
    }
}

  運行測試,輸岀如下結果:

  3

  4.3 操作散列

  Redis hash (散列)是一個string類型的field和value的映射表,hash特別適合用於存儲對象。value中存放的是結構化的對象.利用這種數據結構,可以方便地操作其中的某個欄位。比如在“單點登錄”時,可以用這種數據結構存儲用戶信息。以Cookield作為key,設置30分鐘為緩存過期時間,能很好地模擬出類似Session的效果。

  (1)void putAII(H key, Map<? extends HK, ? extends HV> m)

    用m中提供的多個散列欄位設置到key對應的散列表中,用法見以下代碼:

@SpringBootTest
class RedisApplicationTests {
    @Autowired
    private RedisTemplate redisTemplate;
    @Test
    void test() {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("key1", "value1");
        map.put("key2", "value2");
        redisTemplate.opsForHash().putAll("HASH",map);
        System.out.println(redisTemplate.opsForHash().entries("HASH"));
    }
}

  運行測試,輸出如下結果:

  {key1=value1, key2=value2}

  (2)void put(H key, HK hashKey, HV value)

    設置hashKey的值,用法見以下代碼:

@SpringBootTest
class RedisApplicationTests {
    @Autowired
    private RedisTemplate redisTemplate;
    @Test
    void test() {
        redisTemplate.opsForHash().put("redis","name","li");
        redisTemplate.opsForHash().put("redis","sex","male");
        System.out.println(redisTemplate.opsForHash().entries("redis"));
    }
}

  運行測試,輸出如下結果:

  {name=li, sex=male}

  (3)List<HV> values(H key)

  根據密鑰獲取整個散列存儲的值,用法見以下代碼:

@SpringBootTest
class RedisApplicationTests {
    @Autowired
    private RedisTemplate redisTemplate;
    @Test
    void test() {
        redisTemplate.opsForHash().put("redis","name","li");
        redisTemplate.opsForHash().put("redis","sex","male");
        System.out.println(redisTemplate.opsForHash().values("redis"));
    }
}

  運行測試,輸出如下結果:

  [li, male]

  (4)Map<HK, HV> entries(H key)

  根據密鑰獲取整個散列存儲,用法見以下代碼:

@SpringBootTest
class RedisApplicationTests {
    @Autowired
    private RedisTemplate redisTemplate;
    @Test
    void test() {
        redisTemplate.opsForHash().put("redis","name","li");
        redisTemplate.opsForHash().put("redis","sex","male");
        System.out.println(redisTemplate.opsForHash().entries("redis"));
    }
}

  運行測試,輸出如下結果:

  {name=li, sex=male}

  (5)Long delete(H key, Object... hashKeys)

  刪除給定的hashKeys,用法見以下代碼:

@SpringBootTest
class RedisApplicationTests {
    @Autowired
    private RedisTemplate redisTemplate;
    @Test
    void test() {
        redisTemplate.opsForHash().put("redis","name","li");
        redisTemplate.opsForHash().put("redis","sex","male");
        System.out.println(redisTemplate.opsForHash().delete("redis","name"));
        System.out.println(redisTemplate.opsForHash().entries("redis"));
    }
}

  運行測試,輸出如下結果:

  1
  {sex=male}

  (6)Boolean hasKey(H key, Object hashKey)

  確定hashKey是否存在,用法見以下代碼:

@SpringBootTest
class RedisApplicationTests {
    @Autowired
    private RedisTemplate redisTemplate;
    @Test
    void test() {
        redisTemplate.opsForHash().put("redis","name","li");
        redisTemplate.opsForHash().put("redis","sex","male");
        System.out.println(redisTemplate.opsForHash().hasKey("redis","name"));
        System.out.println(redisTemplate.opsForHash().hasKey("redis","sex"));
    }
}

  運行測試,輸出如下結果:

  true
  true

  (7)HV get(H key, Object hashKey)

  從鍵中的散列獲取給定hashKey的值,用法見以下代碼:

@SpringBootTest
class RedisApplicationTests {
    @Autowired
    private RedisTemplate redisTemplate;
    @Test
    void test() {
        redisTemplate.opsForHash().put("redis","name","li");
        redisTemplate.opsForHash().put("redis","sex","male");
        System.out.println(redisTemplate.opsForHash().get("redis","name"));
    }
}

  運行測試,輸出如下結果:

  li

  (8)Set<HK> keys(H key)

  獲取key所對應的key的值,用法見以下代碼:

@SpringBootTest
class RedisApplicationTests {
    @Autowired
    private RedisTemplate redisTemplate;
    @Test
    void test() {
        redisTemplate.opsForHash().put("redis","name","li");
        redisTemplate.opsForHash().put("redis","sex","male");
        System.out.println(redisTemplate.opsForHash().keys("redis"));
    }
}

  運行測試,輸出如下結果:

  [sex, name]

  (9)Long size(H key)

  獲取key所對應的散列表的大小個數,用法見以下代碼:

@SpringBootTest
class RedisApplicationTests {
    @Autowired
    private RedisTemplate redisTemplate;
    @Test
    void test() {
        redisTemplate.opsForHash().put("redis","name","li");
        redisTemplate.opsForHash().put("redis","sex","male");
        System.out.println(redisTemplate.opsForHash().size("redis"));
    }
}

  運行測試,輸出如下結果:

  2

  4.4 操作列表

  Redis列表是簡單的字元串列表,按照插入順序排序。可以添加一個元素到列表的頭部(左邊) 或尾部(右邊)。

    使用list數據結構,可以做簡單的消息隊列的功能。還可以利用Irange命令,做基於Redis的分頁功能,性能極佳。而使用SQL語句做分頁功能往往效果扱差。

  (1)Long leftPushAII(K key, V... values)

    leftPushAII表示把一個數組插入列表中,用法見以下代碼:

@SpringBootTest
class RedisApplicationTests {
    @Autowired
    private RedisTemplate redisTemplate;
    @Test
    void test() {
        String[] strings = new String[] {"1","2","3"};
        redisTemplate.opsForList().leftPushAll("list",strings);
        System.out.println(redisTemplate.opsForList().range("list",0,-1));
    }
}

  運行測試,輸岀如下結果:

  [3,2,1]

  (2)Long size(K key)

    返回存儲在鍵中的列表的長度。如果鍵不存在,則將其解釋為空列表,並返回0。如果key存儲的值不是列表,則返回錯誤。用法見以下代碼:

@SpringBootTest
class RedisApplicationTests {
    @Autowired
    private RedisTemplate redisTemplate;
    @Test
    void test() {
        String[] strings = new String[] {"1","2","3"};
        redisTemplate.opsForList().leftPushAll("list",strings);
        System.out.println(redisTemplate.opsForList().size("list"));
    }
}

  運行測試,輸岀如下結果:

  6

  (3)Long leftPush(K key, V value)

    將所有指定的值插入在鍵的列表的頭部,如果鍵不存在,則在執行推送操作之前將其創建為空列表(從左邊插入)。用法見以下代碼:

@SpringBootTest
class RedisApplicationTests {
    @Autowired
    private RedisTemplate redisTemplate;
    @Test
    void test() {
        redisTemplate.opsForList().leftPush("list","1");
        System.out.println(redisTemplate.opsForList().size("list"));
        redisTemplate.opsForList().leftPush("list","2");
        System.out.println(redisTemplate.opsForList().size("list"));
        redisTemplate.opsForList().leftPush("list","3");
        System.out.println(redisTemplate.opsForList().size("list"));
    }
}

  (4)Long rightPush(K key, V value)

    將所有指定的值插入存儲在鍵的列表的頭部。如果鍵不存在,則在執行推送操作之前將其創建為空列表(從右邊插入)。用法見以下代碼:

@SpringBootTest
class RedisApplicationTests {
    @Autowired
    private RedisTemplate redisTemplate;
    @Test
    void test() {
        redisTemplate.opsForList().rightPush("list","1");
        System.out.println(redisTemplate.opsForList().size("list"));
        redisTemplate.opsForList().rightPush("list","2");
        System.out.println(redisTemplate.opsForList().size("list"));
        redisTemplate.opsForList().rightPush("list","3");
        System.out.println(redisTemplate.opsForList().size("list"));
    }
}

  (5)Long rightPushAII(K key, V... values)

    通過rightPushAII方法向最右邊批量添加元素,用法見以下代碼:

@SpringBootTest
class RedisApplicationTests {
    @Autowired
    private RedisTemplate redisTemplate;
    @Test
    void test() {
        String[] strings = new String[]{"1", "2", "3"};
        redisTemplate.opsForList().rightPushAll("list",strings);
        System.out.println(redisTemplate.opsForList().range("list",0,-1));
    }
}

  (6)void set(K key, long index, V value)

    在列表中index的位置設置value,用法見以下代碼:

@SpringBootTest
class RedisApplicationTests {
    @Autowired
    private RedisTemplate redisTemplate;
    @Test
    void test() {
        String[] strings = new String[]{"1", "2", "3"};
        redisTemplate.opsForList().rightPushAll("list",strings);
        System.out.println(redisTemplate.opsForList().range("list",0,-1));
        redisTemplate.opsForList().set("list",1,"值");
        System.out.println(redisTemplate.opsForList().range("list",0,-1));
    }
}

  運行測試,輸出如下結果:

  [1, 2, 3]
  [1, 值, 3]

  (7)Long remove(K key, long count, Object value)

   從存儲在鍵中的列表,刪除給定“count”值的元素的第1個計數事件。其中,參數count的 含義如下。

    • count=0:刪除等於value的所有元素。
    • count>0:刪除等於從頭到尾移動的值的元素:
    • counK<0:刪除等於從尾到頭移動的值的元素。

以下代碼用於刪除列表中第一次出現的值。

@SpringBootTest
class RedisApplicationTests {
    @Autowired
    private RedisTemplate redisTemplate;
    @Test
    void test() {
        String[] strings = new String[]{"1", "2", "3"};
        redisTemplate.opsForList().rightPushAll("list",strings);
        System.out.println(redisTemplate.opsForList().range("list",0,-1));
        redisTemplate.opsForList().remove("list",1,"2");
        System.out.println(redisTemplate.opsForList().range("list",0,-1));
    }
}

  運行測試,輸出如下結果:

  [1, 2, 3]
  [1, 3]

  (8)V index(K key, long index)

    根據下標獲取列表中的值(下標從0幵始),用法見以下代碼:

@SpringBootTest
class RedisApplicationTests {
    @Autowired
    private RedisTemplate redisTemplate;
    @Test
    void test() {
        String[] strings = new String[]{"1", "2", "3"};
        redisTemplate.opsForList().rightPushAll("list",strings);
        System.out.println(redisTemplate.opsForList().range("list",0,-1));
        System.out.println(redisTemplate.opsForList().index("list",2));
    }
}

  運行測試,輸出如下結果:

  [1, 2, 3]
  3

  (9)V leftPop(K key)

    彈出最左邊的元素,彈出之後該值在列表中將不復存在,用法見以下代碼:

@SpringBootTest
class RedisApplicationTests {
    @Autowired
    private RedisTemplate redisTemplate;
    @Test
    void test() {
        String[] strings = new String[]{"1", "2", "3"};
        redisTemplate.opsForList().rightPushAll("list",strings);
        System.out.println(redisTemplate.opsForList().range("list",0,-1));
        System.out.println(redisTemplate.opsForList().leftPop("list"));
        System.out.println(redisTemplate.opsForList().range("list",0,-1));

    }
}

  運行測試,出如下結果:

  [1, 2, 3]
  1
  [2, 3]

  (10)V rightPop(K key)

    彈出最右邊的元素,彈出之後該值任列表中將不復存在,用法見以下代碼:

@SpringBootTest
class RedisApplicationTests {
    @Autowired
    private RedisTemplate redisTemplate;
    @Test
    void test() {
        String[] strings = new String[]{"1", "2", "3"};
        redisTemplate.opsForList().rightPushAll("list",strings);
        System.out.println(redisTemplate.opsForList().range("list",0,-1));
        System.out.println(redisTemplate.opsForList().rightPop("list"));
        System.out.println(redisTemplate.opsForList().range("list",0,-1));

    }
}

  運行測試,輸出如下結果:

  [1, 2, 3]
  3
  [1, 2]

 4.5 操作集合

  set是存放不重覆值的集合。利用set可以做全局去重的功能。還可以進行交集、並集、差集等 操作,也可用來實現計算共同喜好、全部的喜好、自己獨有的喜好等功能。

  Redis的set是string類型的無序集合,通過散列表實現。

  (1)Long add(K key, .. values)

    在無序集合中添加元素,返回添加個數,用法見以下代碼:

@SpringBootTest
class RedisApplicationTests {
    @Autowired
    private RedisTemplate redisTemplate;
    @Test
    void test() {
        String[] strings = new String[]{"str1", "str2"};
        System.out.println(redisTemplate.opsForSet().add("set1",strings));
        System.out.println(redisTemplate.opsForSet().add("set1","1","2","3"));
    }
}

  運行測試,輸出如下結果:

  2

  3

  (2)Long remove(K key, Object... values)

    移除集合中一個或多個成員,用法見以下代碼:

@SpringBootTest
class RedisApplicationTests {
    @Autowired
    private RedisTemplate redisTemplate;
    @Test
    void test() {
        String[] strings = new String[]{"str1", "str2"};
        System.out.println(redisTemplate.opsForSet().add("set1",strings));
        System.out.println(redisTemplate.opsForSet().remove("set1",strings));
    }
}

  運行測試,輸出如下結果:

  2

  0

  (3)V pop(K key)

    移除並返回集合中的一個隨機元素,用法見以下代碼:

@SpringBootTest
class RedisApplicationTests {
    @Autowired
    private RedisTemplate redisTemplate;
    @Test
    void test() {
        String[] strings = new String[]{"str1", "str2"};
        System.out.println(redisTemplate.opsForSet().add("set1",strings));
        System.out.println(redisTemplate.opsForSet().pop("set1"));
        System.out.println(redisTemplate.opsForSet().members("set1"));
    }
}

  運行測試,輸出如下結果:

  2
  str2
  [str1]

  (4)Boolean move(K key, V value, K destKey)

    將member元素移動,用法見以下代碼:

@SpringBootTest
class RedisApplicationTests {
    @Autowired
    private RedisTemplate redisTemplate;
    @Test
    void test() {
        String[] strings = new String[]{"str1", "str2"};
        System.out.println(redisTemplate.opsForSet().add("set1",strings));
        redisTemplate.opsForSet().move("set1","str1","set1tostr1");
        System.out.println(redisTemplate.opsForSet().members("set1"));
        System.out.println(redisTemplate.opsForSet().members("set1tostr1"));
    }
}

  運行測試,輸出如下結果:

  2
  [str2]
  [str1]

  (5)Long size(K key)

    獲取無序集合的大小長度,用法見以下代碼:

@SpringBootTest
class RedisApplicationTests {
    @Autowired
    private RedisTemplate redisTemplate;
    @Test
    void test() {
        String[] strings = new String[]{"str1", "str2"};
        System.out.println(redisTemplate.opsForSet().add("set",strings));
        System.out.println(redisTemplate.opsForSet().size("set"));
    }
}

  運行測試,輸出如下結果:

  2

  2

  (6)Set<V> members(K key)

    返回集合中的所有成員,用法見以下代碼:

@SpringBootTest
class RedisApplicationTests {
    @Autowired
    private RedisTemplate redisTemplate;
    @Test
    void test() {
        String[] strings = new String[]{"str1", "str2"};
        System.out.println(redisTemplate.opsForSet().add("set",strings));
        System.out.println(redisTemplate.opsForSet().members("set"));
    }
}

  運行測試,輸出如下結果:

  2

  [str1,str2]

  (7)Cursor<V> scan(K key, ScanOptions options)

    遍歷Set,用法見以下代碼:

@SpringBootTest
class RedisApplicationTests {
    @Autowired
    private RedisTemplate redisTemplate;
    @Test
    void test() {
        String[] strings = new String[]{"str1", "str2"};
        System.out.println(redisTemplate.opsForSet().add("set",strings));
        Cursor<Object> cursor = redisTemplate.opsForSet().scan("set", ScanOptions.NONE);
        while (cursor.hasNext()) {
            System.out.println(cursor.next());
        }
    }
}

  運行測試,輸岀如下結果:

  2

  str2

  str1

  4.6 操作有序集合

  zset (sorted set,有序集合)也是string類型元素的集合,且不允許重覆的成員。每個元素都會關聯一個double類型的分數。可以通過分數將該集合中的成員從小到大進行排序。

  zset的成員是唯一的,但權重參數分數(score)卻可以重覆。集合中的元素能夠按score進行排列。它可以用來做排行榜應用、取TOP N 延時任務、範圍查找等。

  (1)Long add(K key, Set<TypedTuple<V>>tuples)

    新增一個有序集合,用法見以下代碼:

@SpringBootTest
class RedisApplicationTests {
    @Autowired
    private RedisTemplate redisTemplate;
    @Test
    void test() {
        ZSetOperations.TypedTuple<Object> objectTypedTuple1 = new DefaultTypedTuple<>("zset-1",9.6);
        ZSetOperations.TypedTuple<Object> objectTypedTuple2 = new DefaultTypedTuple<>("zset-2",9.9);
        Set<ZSetOperations.TypedTuple<Object>> tuples = new HashSet<>();
        tuples.add(objectTypedTuple1);
        tuples.add(objectTypedTuple2);
        System.out.println(redisTemplate.opsForZSet().add("zset",tuples));
        System.out.println(redisTemplate.opsForZSet().range("zset",0,-1));
    }
}

  運行測試,輸出如下結果:

  1
  [zset-1, zset-2]

  (2)Boolean add(K key, V value, double score)

    新增一個有序集合,如果存在則返回false,如果不存在則返回true,用法見以下代碼:

@SpringBootTest
class RedisApplicationTests {
    @Autowired
    private RedisTemplate redisTemplate;
    @Test
    void test() {
        System.out.println(redisTemplate.opsForZSet().add("zset","zset-1",1.0));
        System.out.println(redisTemplate.opsForZSet().add("zset","zset-1",1.0));
    }
}

   運行測試,輸出如下結果:

  true
  false

  (3)Long remove(K key, Object... values)

    從有序集合中移除一個或多個元素,用法見以下代碼:

@SpringBootTest
class RedisApplicationTests {
    @Autowired
    private RedisTemplate redisTemplate;
    @Test
    void test() {
        System.out.println(redisTemplate.opsForZSet().add("zset","zset-1",1.0));
        System.out.println(redisTemplate.opsForZSet().add("zset","zset-2",1.0));
        System.out.println(redisTemplate.opsForZSet().range("zset",0,-1));
        System.out.println(redisTemplate.opsForZSet().remove("zset","zset-2"));
        System.out.println(redisTemplate.opsForZSet().range("zset",0,-1));
    }
}

  運行測試,輸出如下結果:

  true
  true
  [zset-1, zset-2]
  1
  [zset-1]

  (4)Long rank(K key, Object o)

    返回有序集中指定成員的排名,按分數值遞增排列,用法見以下代碼:

@SpringBootTest
class RedisApplicationTests {
    @Autowired
    private RedisTemplate redisTemplate;
    @Test
    void test() {
        System.out.println(redisTemplate.opsForZSet().add("zset","zset-1",1.0));
        System.out.println(redisTemplate.opsForZSet().add("zset","zset-2",1.0));
        System.out.println(redisTemplate.opsForZSet().range("zset",0,-1));
        System.out.println(redisTemplate.opsForZSet().remove("rank","zset-1"));
    }
}

  運行測試,輸出如下結果:

  true
  true
  [zset-1, zset-2]
  0

  (5)Set<V> range(K key, long start, long end)

    通過索引區間返回有序集合指定區間內的成員,按分數值遞增排列,用法見以下代碼:

@SpringBootTest
class RedisApplicationTests {
    @Autowired
    private RedisTemplate redisTemplate;
    @Test
    void test() {
        ZSetOperations.TypedTuple<Object> objectTypedTuple1 = new DefaultTypedTuple<>("zset-1",9.6);
        ZSetOperations.TypedTuple<Object> objectTypedTuple2 = new DefaultTypedTuple<>("zset-2",8.1);
        Set<ZSetOperations.TypedTuple<Object>> tuples = new HashSet<>();
        tuples.add(objectTypedTuple1);
        tuples.add(objectTypedTuple2);
        System.out.println(redisTemplate.opsForZSet().add("zset",tuples));
        System.out.println(redisTemplate.opsForZSet().range("zset",0,-1));
    }
}

  運行測試,輸出如下結果:

  0
  [zset-2, zset-1]

  (6)Long count(K key, double min, double max)

    通過分數返回有序集合指定區間內的成員個數,用法見以下代碼:

@SpringBootTest
class RedisApplicationTests {
    @Autowired
    private RedisTemplate redisTemplate;
    @Test
    void test() {
        ZSetOperations.TypedTuple<Object> objectTypedTuple1 = new DefaultTypedTuple<>("zset-1",3.6);
        ZSetOperations.TypedTuple<Object> objectTypedTuple2 = new DefaultTypedTuple<>("zset-2",4.1);
        ZSetOperations.TypedTuple<Object> objectTypedTuple3 = new DefaultTypedTuple<>("zset-3",5.7);
        Set<ZSetOperations.TypedTuple<Object>> tuples = new HashSet<>();
        tuples.add(objectTypedTuple1);
        tuples.add(objectTypedTuple2);
        tuples.add(objectTypedTuple3);
        System.out.println(redisTemplate.opsForZSet().add("zset",tuples));
        System.out.println(redisTemplate.opsForZSet().rangeByScore("zset",0,9));
        System.out.println(redisTemplate.opsForZSet().count("zset",0,5));
    }
}

  運行測試,輸出如下結果:

  1
  [zset-1, zset-2, zset-3]
  2

  (7)Long size(K key)

    獲取有序集合的成員數,用法見以下代碼:

@SpringBootTest
class RedisApplicationTests {
    @Autowired
    private RedisTemplate redisTemplate;
    @Test
    void test() {
        ZSetOperations.TypedTuple<Object> objectTypedTuple1 = new DefaultTypedTuple<>("zset-1",3.6);
        ZSetOperations.TypedTuple<Object> objectTypedTuple2 = new DefaultTypedTuple<>("zset-2",4.1);
        ZSetOperations.TypedTuple<Object> objectTypedTuple3 = new DefaultTypedTuple<>("zset-3",5.7);
        Set<ZSetOperations.TypedTuple<Object>> tuples = new HashSet<>();
        tuples.add(objectTypedTuple1);
        tuples.add(objectTypedTuple2);
        tuples.add(objectTypedTuple3);
        System.out.println(redisTemplate.opsForZSet().add("zset",tuples));
        System.out.println(redisTemplate.opsForZSet().size("zset"));
    }
}

  運行測試,輸出如下結果:

  0
  3  

  (8)Double score(K key, Object o)

    獲取指定成員的score值,用法見以下代碼:

@SpringBootTest
class RedisApplicationTests {
    @Autowired
    private RedisTemplate redisTemplate;
    @Test
    void test() {
        ZSetOperations.TypedTuple<Object> objectTypedTuple1 = new DefaultTypedTuple<>("zset-1",3.6);
        ZSetOperations.TypedTuple<Object> objectTypedTuple2 = new DefaultTypedTuple<>("zset-2",4.1);
        ZSetOperations.TypedTuple<Object> objectTypedTuple3 = new DefaultTypedTuple<>("zset-3",5.7);
        Set<ZSetOperations.TypedTuple<Object>> tuples = new HashSet<>();
        tuples.add(objectTypedTuple1);
        tuples.add(objectTypedTuple2);
        tuples.add(objectTypedTuple3);
        System.out.println(redisTemplate.opsForZSet().add("zset",tuples));
        System.out.println(redisTemplate.opsForZSet().score("zset","zset-1"));
    }
}

  運行測試,輸出如下結果:

  0
  3.6

  (9)Long removeRange(K key, long start, long end)

    移除指定索引位置的成員,有序集成員按分數值遞增排列,用法見以下代碼:

@SpringBootTest
class RedisApplicationTests {
    @Autowired
    private RedisTemplate redisTemplate;
    @Test
    void test() {
        ZSetOperations.TypedTuple<Object> objectTypedTuple1 = new DefaultTypedTuple<>("zset-1",3.6);
        ZSetOperations.TypedTuple<Object> objectTypedTuple2 = new DefaultTypedTuple<>("zset-2",4.1);
        ZSetOperations.TypedTuple<Object> objectTypedTuple3 = new DefaultTypedTuple<>("zset-3",2.7);
        Set<ZSetOperations.TypedTuple<Object>> tuples = new HashSet<>();
        tuples.add(objectTypedTuple1);
        tuples.add(objectTypedTuple2);
        tuples.add(objectTypedTuple3);
        System.out.println(redisTemplate.opsForZSet().add("zset",tuples));
        System.out.println(redisTemplate.opsForZSet().range("zset",0,-1));
        System.out.println(redisTemplate.opsForZSet().removeRange("zset",1,2));
        System.out.println(redisTemplate.opsForZSet().range("zset",0,-1));
    }
}

  運行測試,輸岀如下結果:

  2
  [zset-3, zset-1, zset-2]
  2
  [zset-3]

  (10)Cursor<TypedTuple<V>>scan(K key, ScanOptions options)

    遍歷zset,用法見以下代碼:

@SpringBootTest
class RedisApplicationTests {
    @Autowired
    private RedisTemplate redisTemplate;
    @Test
    void test() {
        ZSetOperations.TypedTuple<Object> objectTypedTuple1 = new DefaultTypedTuple<>("zset-1",3.6);
        ZSetOperations.TypedTuple<Object> objectTypedTuple2 = new DefaultTypedTuple<>("zset-2",5.1);
        ZSetOperations.TypedTuple<Object> objectTypedTuple3 = new DefaultTypedTuple<>("zset-3",2.7);
        Set<ZSetOperations.TypedTuple<Object>> tuples = new HashSet<>();
        tuples.add(objectTypedTuple1);
        tuples.add(objectTypedTuple2);
        tuples.add(objectTypedTuple3);
        System.out.println(redisTemplate.opsForZSet().add("zset",tuples));
        Cursor<ZSetOperations.TypedTuple<Object>> cursor = redisTemplate.opsForZSet().scan("zset",ScanOptions.NONE);
        while (cursor.hasNext()) {
            ZSetOperations.TypedTuple<Object> item = cursor.next();
            System.out.println(item.getValue()+":"+item.getScore());
        }
    }
}

  運行測試,輸出如下結果:

  2
  zset-3:2.7
  zset-1:3.6
  zset-2:5.1

  除使用opsForXXX方法外,還可以使用Execute方法。opsForXXX方法的底層,是通過調用Execute方法來實現的。psForXXX方法實際上是封裝了 Execute方法,定義了序列化,以便使用起來更簡單便捷。

  4.7 比較 RedisTemplate 和 StringRedisTemplate

  StringRedisTemplate繼承於RedisTemplate,兩者的數據是不相通的。

  • StringRedisTemplate 只能管理 StringRedisTemplate 中的數據。
  • RedisTemplate 只能管理 RedisTemplate 中的數據。

  StnngRedisTemplate預設採用的是string的序列化策略,RedisTemplate預設採用的是 JDK的序列化策略。

  

  


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 函數是基於功能或者邏輯進行聚合的可復用的代碼塊。將一些複雜的、冗長的代碼抽離封裝成多個代碼片段,即函數,有助於提高代碼邏輯的可讀性和可維護性。不同於Python,由於 Go lang是編譯型語言,編譯之後再運行,所以函數的定義順序無關痛癢。 函數聲明 在 Go lang里,函數聲明語法如下: fun ...
  • 《Python高手之路 第3版》|免費下載地址 作者簡介 · · · · · · Julien Danjou 具有12年從業經驗的自由軟體黑客。擁有多個開源社區的不同身份:Debian開發者、Freedesktop貢獻者、GNU Emacs提交者、awesome視窗管理器的創建者以及OpenStac ...
  • 《紅樓夢》作為我國四大名著之一,古典小說的巔峰之作,粉絲量極其龐大,而紅學也經久不衰。所以我們今天通過 Python 來探索下紅樓夢裡那千絲萬縷的人物關係,話不多說,開始整活! 一、準備工作 紅樓夢txt格式電子書一份 金陵十二釵+賈寶玉人物名稱列表 寶玉 nr 黛玉 nr 寶釵 nr 湘雲 nr ...
  • “什麼是IO的多路復用機制?” 這是一道年薪50W的面試題,很遺憾,99%的人都回答不出來。 大家好,我是Mic,一個工作了14年的Java程式員。 今天,給大家分享一道網路IO的面試題。 這道題目的文字回答已經整理到了15W字的面試文檔裡面,大家可以S我領取。 下麵看看高手的回答。 高手: IO多 ...
  • 多商戶商城系統,也稱為B2B2C(BBC)平臺電商模式多商家商城系統。可以快速幫助企業搭建類似拼多多/京東/天貓/淘寶的綜合商城。 多商戶商城系統支持商家入駐加盟,同時滿足平臺自營、旗艦店等多種經營方式。平臺可以通過收取商家入駐費,訂單交易服務費,提現手續費,簡訊通道費等多手段方式,實現整體盈利。 ...
  • 原文連接:https://www.zhoubotong.site/post/67.html Go 標準庫的net/url包提供的兩個函可以直接檢查URL合法性,不需要手動去正則匹配校驗。 下麵可以直接使用ParseRequestURI()函數解析URL,當然這個只會驗證url格式,至於功能變數名稱是否存在或 ...
  • Python帶我起飛——入門、進階、商業實戰_ 免費下載地址 內容簡介 · · · · · · 《Python帶我起飛——入門、進階、商業實戰》針對Python 3.5 以上版本,採用“理論+實踐”的形式編寫,通過大量的實例(共42 個),全面而深入地講解“Python 基礎語法”和“Python ...
  • 1、應用場景 1.1 kafka場景 ​ Kafka最初是由LinkedIn公司採用Scala語言開發,基於ZooKeeper,現在已經捐獻給了Apache基金會。目前Kafka已經定位為一個分散式流式處理平臺,它以 高吞吐、可持久化、可水平擴展、支持流處理等多種特性而被廣泛應用。 ​ Apache ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...