Redis筆記 - 02

Redis的特性

  • Strings:Strings 數據結構是簡單的key-value類型,value其實不僅是String,也可以是數字.
    常用命令: set,get,decr,incr,mget 等。
    常用方法:

    1. 獲取字符串長度
    2. 往字符串append內容
    3. 設置和獲取字符串的某一段內容
    4. 設置及獲取字符串的某一位(bit)
    5. 批量設置一系列字符串的內容
  • Hashs:Redis Hash對應Value內部實際就是一個HashMap,常用命令:hget,hset,hgetall 等。

  • Lists:Redis list的實現爲一個雙向鏈表,即可以支持反向查找和遍歷,更方便操作,不過帶來了部分額外的內存開銷,Redis內部的很多實現,包括髮送緩衝隊列等也都是用的這個數據結構。
    常用命令:lpush,rpush,lpop,rpop,lrange等。

  • Sets:Sets 集合的概念就是一堆不重複值的組合。Redis還爲集合提供了求交集、並集、差集等操作,可以非常方便的實現如共同關注、共同喜好、二度好友等功能。
    常用命令:sadd,spop,smembers,sunion 等。

  • Sorted Sets:Redis sorted set的使用場景與set類似,區別是set不是自動有序的。sorted set可以通過用戶額外提供一個優先級(score)的參數來爲成員排序,並且是插入有序的,即自動排序。
    常用命令:zadd,zrange,zrem,zcard等

下面就根據這幾個特性,也就是Redis支持的數據類型,來完成以下場景的實現。

場景一:簡單計數功能

Redis是一個很好的計數器,計數器是 Redis 的原子性自增操作可實現的最直觀的模式了,它的想法相當簡單:每當某個操作發生時,向 Redis 發送一個 INCR 命令。使用場景比如網站的訪問數,註冊用戶數,文章的點贊數,高併發的秒殺活動,分佈式序列號生成等等統計計數的功能實現。Redis 解決這類計數問題得心應手,相比關係數據庫速度更快,消耗資源更少。還可以通過set()方法來重置計數。

// 簡單計數
	@Test
	public void test1() {
		try {
			ValueOperations<String, String> opsForValue = stringRedisTemplate.opsForValue();
			//計數前打印
			System.out.println(opsForValue.get("test1"));
			for (int i = 0; i < 100; i++) {
				//計數,第一個參數爲key值,第二個參數爲每次增加計數的單位
				opsForValue.increment("test1", 1);
			}
			//計數後打印
			System.out.println(opsForValue.get("test1"));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

場景二:按時間統計計數

有時候除了簡單的計數外,比如註冊用戶數需要按日統計,處理方法比較簡單,把日期帶入計數器 key 就可以。以此類推,還可以按其他方式進行統計計數,只需要把統計的方式添加到key值就可以了

// 按時間計數 
	@Test
	public void test2() {
		//將日期添加到key值中
		String key = "test2_" + new SimpleDateFormat("yyyy-MM-dd").format(new Date());
		try {
			ValueOperations<String, String> opsForValue = stringRedisTemplate.opsForValue();
			System.out.println(opsForValue.get(key));
			for (int i = 0; i < 100; i++) {
				opsForValue.increment(key, 1);
			}
			System.out.println(opsForValue.get(key));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

場景三:按模糊Key值查詢

在按條件統計計數的時候,把時間加入到了key值中,有時候要只是查詢某個對象的統計數時,就可以使用模糊Key值查詢。

// 模糊K值查詢
	@Test
	public void test3() {
		try {
			ValueOperations<String, String> opsForValue = stringRedisTemplate.opsForValue();
			//先獲取前綴爲test的Key值列表。
			Set<String> keys = stringRedisTemplate.keys("test*");
			//遍歷滿足條件的Key值獲取對應的value值
			for (String a : keys) {
				System.out.println(a + ":" + opsForValue.get(a));
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

場景四:設置Key的有效時間(防止高併發訪問)

在redis中可以設置key值的有效時間,用戶訪問鏈接的時候,將用戶的唯一信息比如ip地址等爲key值,時間爲value值,在redis中記錄一下,在用戶再次訪問的時候,通過key值獲取前一次訪問的時間,比較時間的間隔,如果低於閥值,就拒絕這次請求,防止用戶多次訪問。這裏只是寫下在spring的RedisTemplate接口怎麼使用。具體的邏輯實現自己搞定。

// 設置key值的有效時間
	@Test
	public void test4() {
		try {
			ValueOperations<String, String> opsForValue = stringRedisTemplate.opsForValue();
			opsForValue.set("test4", "test4");
			System.out.println(opsForValue.get("test4"));
			// TimeUnit.SECONDS:解釋定時參數的單位
			// MICROSECONDS 微秒 一百萬分之一秒(就是毫秒/1000)
			// MILLISECONDS 毫秒 千分之一秒
			// NANOSECONDS 毫微秒 十億分之一秒(就是微秒/1000)
			// SECONDS 秒
			// MINUTES 分鐘
			// HOURS 小時
			// DAYS 天
			if(stringRedisTemplate.expire("test4", 5, TimeUnit.SECONDS)){
				System.out.println("設置過期時間成功,等待。。。。");
				Thread.sleep(5001);
			}
			System.out.println(opsForValue.get("test4"));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

場景五:使用hashs存儲獲取修改java對象

在實際開發中,我們經常將一些結構化的信息打包成HashMap,在客戶端序列化後存儲爲一個字符串的值,比如用戶的暱稱、年齡、性別、積分等,這時候在需要修改其中某一項時,通常需要將所有值取出反序列化後,修改某一項的值,再序列化存儲回去。這樣不僅增大了開銷,也不適用於一些可能併發操作的場合(比如兩個併發的操作都需要修改積分)。

而Redis的Hash結構可以使你像在數據庫中Update一個屬性一樣只修改某一項屬性值。因爲Redis的Hash結構是以對象的名字作爲redis的key值,以對象的唯一屬性值作爲hash的key值,以對象來作爲redis的value值。結構圖如下:

                              hashs存儲結構圖

                                                          hashs存儲結構圖

// 使用hashs存儲獲取對象
	@Test
	public void test5(){
		BeautifulPictures beautifulPictures = beautifulPicturesService.selectById(1);
		HashOperations<String, Object, BeautifulPictures> hash = redisTemplate.opsForHash();
		hash.put("test5",beautifulPictures.getId(),beautifulPictures);
		System.out.println(hash.get("test5", beautifulPictures.getId()));
	}

場景六:使用lists有序存儲讀取

適用於獲取最近N個操作的數據。

 

//使用lists存儲讀取 有序
	@Test
	public void test6(){
		ListOperations<String, String> list = stringRedisTemplate.opsForList();
		list.leftPush("test6", "1");
		list.leftPush("test6", "2");
		list.leftPush("test6", "3");
		list.leftPush("test6", "4");
		list.leftPush("test6", "5");
		list.leftPush("test6", "6");
		list.leftPush("test6", "7");
		//保持鏈表只有3位
		list.trim("test6", 0, 2);
		System.out.println(list.range("test6", 0, list.size("test6")-1));
	}

場景七:使用sets存儲讀取 無序 去重 求差集,交集,並集

//使用set存儲讀取  無序 去重  求差集,交集,並集
	@Test
	public void test7(){
		SetOperations<String, String> set = stringRedisTemplate.opsForSet();
		set.add("test7_1", "2", "1","2","3","4","4","3");
		set.add("test7_2", "2", "6","2","3","7","6","5");
		System.out.println("全部成員"+set.members("test7_1"));
		System.out.println("差集"+set.difference("test7_1", "test7_2"));
		System.out.println("交集"+set.intersect("test7_1", "test7_2"));
		System.out.println("並集"+set.union("test7_1", "test7_2"));
	}

場景八:Sorted Set 存取數據 排序

//Sorted Set 存取數據 排序  相比sets 保存時多一個權重參數score,相當於按照此參數來排序
	@Test
	public void test8(){
		ZSetOperations<String, String> zSet = stringRedisTemplate.opsForZSet();
		zSet.add("test8", "use1", 9);
		zSet.add("test8", "use2", 1);
		zSet.add("test8", "use3", 5);
		zSet.add("test8", "use4", 9);
		//對應的score值增加
		//zSet.incrementScore("test8", "use1", 1);
		System.out.println(zSet.reverseRange("test8", 0, zSet.size("test8")-1));
	}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章