主頁 > 後端開發 > redis-SpringBoot(21)

redis-SpringBoot(21)

2022-08-12 07:20:16 後端開發

??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= "https://www.cnblogs.com/liwenruo/archive/2022/08/11/cache1" )、@Cacheable(value=https://www.cnblogs.com/liwenruo/archive/2022/08/11/{"cache1" , "cache2n },
    • key:快取的key可以為空,如果自定義key,則要按照SpEL運算式撰寫,可以自動按照方法的引陣列合,如,@Cacheable(value= "https://www.cnblogs.com/liwenruo/archive/2022/08/11/cache1",key= "#id” )
    • condition:快取的條件可以為空,如果自定義condition,則使用SpEL運算式輻寫,以返 回true或false值,只有回傳true才進行快取,如,@Cacheable(value= https://www.cnblogs.com/liwenruo/archive/2022/08/11/“cache1" ,condition= "#id.length()>2" ),

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

@Override
@Cacheable(value = "https://www.cnblogs.com/liwenruo/archive/2022/08/11/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 = "https://www.cnblogs.com/liwenruo/archive/2022/08/11/usr",key = "targetClass + #p0")
public Book update(Book book) {
    return null;
}

@Override
@Cacheable(value = "https://www.cnblogs.com/liwenruo/archive/2022/08/11/usr",key = "targetClass + #p0")
public Book save(Book book) {
    return null;
}

??4. @CacheEvict

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

@Override
@Cacheable(value = "https://www.cnblogs.com/liwenruo/archive/2022/08/11/usr",key = "#p0.id")
public Book save(Book book) {
    return null;
}

@Override
@CacheEvict(value = "https://www.cnblogs.com/liwenruo/archive/2022/08/11/usr",key = "#id")
public void delete(int id) {
}

@Override
@CacheEvict(value = "https://www.cnblogs.com/liwenruo/archive/2022/08/11/accountCache",allEntries = true)
public void deleteAll() {

}

@Override
@CacheEvict(value = "https://www.cnblogs.com/liwenruo/archive/2022/08/11/accountCache",beforeInvocation = true)
public void deleteAll() {

}

??5. @Caching

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

@Override
@Caching(cacheable = {@Cacheable(value = "https://www.cnblogs.com/liwenruo/archive/2022/08/11/usr",key = "#p0"),},
         put = {@CachePut(value = "https://www.cnblogs.com/liwenruo/archive/2022/08/11/usr",key = "#p0"),},
         evict = {@CacheEvict(value = "https://www.cnblogs.com/liwenruo/archive/2022/08/11/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 = "https://www.cnblogs.com/liwenruo/archive/2022/08/11/usr",key = "targetClass + #p0")
    public Book update(Book book) {
        return null;
    }

    @Override
    @Caching(cacheable = {@Cacheable(value = "https://www.cnblogs.com/liwenruo/archive/2022/08/11/usr",key = "#p0"),},
            put = {@CachePut(value = "https://www.cnblogs.com/liwenruo/archive/2022/08/11/usr",key = "#p0"),},
            evict = {@CacheEvict(value = "https://www.cnblogs.com/liwenruo/archive/2022/08/11/usr",key = "#p0"),})
    public Book save(Book book) {
        return null;
    }

    @Override
    @CacheEvict(value = "https://www.cnblogs.com/liwenruo/archive/2022/08/11/usr",key = "#id")
    public void delete(int id) {
    }

    @Override
    @CacheEvict(value = "https://www.cnblogs.com/liwenruo/archive/2022/08/11/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 = "https://www.cnblogs.com/get",method = RequestMethod.GET,produces = "application/json")
    public Book get(){
        Book book = new Book();
        book.setUsername("拉行啊");
        book.setPassword("123");
        return book;
    }
    @RequestMapping(value = "https://www.cnblogs.com/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 = "https://www.cnblogs.com/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 = "https://www.cnblogs.com/liwenruo/archive/2022/08/11/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的序列化策略,

??

??

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/501596.html

標籤:其他

上一篇:pytest分布式執行插件 pytest-xdist 的高級用法

下一篇:【詳細教程】Kafka應用場景、基礎組件、架構探索

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more