一、启动redis服务器
E:\redis 点开redis-server.exe
二、部署
1.
<!-- Redis缓存整合开始 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data- redis</artifactId>
</dependency>
2.
spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf-8 spring.datasource.username =root spring.datasource.password =123 spring.redis.database=0 spring.redis.host=127.0.0.1 spring.redis.port=6379 spring.redis.timeout=3000
三.使用
1.redis存贮初级字符串
1)
package com.po.controller; import com.po.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.concurrent.TimeUnit; @RestController @RequestMapping("/user") public class User { @Autowired private StringRedisTemplate redisTemplate; @RequestMapping("/getpo1") public Object getPo() { //存储字符串 redisTemplate.opsForValue().set("po1", "lan1"); System.out.println("修改前的值: " + redisTemplate.opsForValue().get("po1")); //拼接值 redisTemplate.opsForValue().append("po1", "lupo1"); System.out.println("修改后的值: " + redisTemplate.opsForValue().get("po1")); //直接覆盖值 redisTemplate.opsForValue().set("po1","lupoplus"); System.out.println("覆盖后的值: " + redisTemplate.opsForValue().get("po1")); //重命名key redisTemplate.rename("po1","po1s"); System.out.println("重命名oldKey: " + redisTemplate.opsForValue().get("po1")); System.out.println("重命名newKey: " + redisTemplate.opsForValue().get("po1s")); //删除 redisTemplate.delete("po1s"); System.out.println("删除后的值: " + redisTemplate.opsForValue().get("po1")); //根据key值做value+1 redisTemplate.opsForValue().set("po2","100"); redisTemplate.boundValueOps("po2").increment(1); System.out.println("value自动加1:"+redisTemplate.opsForValue().get("po2")); //根据key值做value-1 redisTemplate.boundValueOps("po2").increment(-1); System.out.println("value自动减1:"+redisTemplate.opsForValue().get("po2")); //设置有效时间2s redisTemplate.opsForValue().set("pos","lanp2",2, TimeUnit.SECONDS); System.out.println("有效期内获取值: " + redisTemplate.opsForValue().get("pos")); //获取有效期时间并换成指定的时间 System.out.println("获取过期时间值: " + redisTemplate.getExpire("pos",TimeUnit.SECONDS)); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("有效期后获取值:" + redisTemplate.opsForValue().get("pos")); //检查key是否存在 System.out.println("pos的haskey: "+redisTemplate.hasKey("pos") +" 是否存在posPlus: "+redisTemplate.hasKey("posPlus")); return "ok"; } }
修改前的值: lan1 修改后的值: lan1lupo1 覆盖后的值: lupoplus 重命名oldKey: null 重命名newKey: lupoplus 删除后的值: null value自动加1:101 value自动减1:100 有效期内获取值: lanp2 获取过期时间值: 1 有效期后获取值:null pos的haskey: false 是否存在posPlus: false
2)字符串2
//判断是否存在 redisTemplate.opsForValue().set("po1","lupoplus"); System.out.println("ss1 "+redisTemplate.opsForValue().setIfAbsent("po1","lan1")); System.out.println("ss2 "+redisTemplate.opsForValue().setIfAbsent("pop","lan2")); //存多个键值 Map<String, String> map = new HashMap<>(); map.put("s1","100"); map.put("s2","200"); map.put("s3","300"); map.put("s4","400"); List<String> list = new ArrayList<>(); list.add("s1"); list.add("s2"); list.add("s3"); list.add("s4"); redisTemplate.opsForValue().multiSet(map); //批量获取值 System.out.println("map:value = "+redisTemplate.opsForValue().multiGet(list)); //截取字符串的长度 System.out.println("截取到的长度:"+ redisTemplate.opsForValue().get("po1",0,4));
ss1 false ss2 true //s为true代表该键不存在,同时将该键存起来,value为null map:value = [100, 200, 300, 400] 截取到的长度:lupop
2.redis的List数据结构
1)
//将所有指定的值插入存储在键的列表的头部。如果键不存在, // 则在执行推送操作之前将其创建为空列表。(从左边插入) redisTemplate.opsForList().leftPush("LL1","a1"); redisTemplate.opsForList().leftPush("LL1","a2"); redisTemplate.opsForList().leftPush("LL1","a3"); //批量把一个数组插入到列表中 List<String> list1 = new ArrayList<>(); list1.add("b1"); list1.add("b2"); list1.add("b3"); String[] str = {"q1","q2","q3"}; redisTemplate.opsForList().leftPushAll("LL2",list1); redisTemplate.opsForList().leftPushAll("str",str); /* Long leftPush(K key, V pivot, V value); 把value值放到key对应列表中pivot值的左面, 如果pivot值存在的话*/ redisTemplate.opsForList().leftPush("LL2", "b2","b2b"); System.out.println("LL1: "+redisTemplate.opsForList().range("LL1",0,-1)); System.out.println("LL2: "+redisTemplate.opsForList().range("LL2",0,-1)); System.out.println("str: "+redisTemplate.opsForList().range("str",0,-1)); return "ok";
LL1: [a3, a2, a1]
LL2: [b3, b2b, b2, b1]
str: [q3, q2, q1]
注意:rightPush,rightOushAll和上面类似。
2)
//在在列表中index的位置设置value值 redisTemplate.opsForList().set("LL2", 1, "pop"); System.out.println("修改指定的位置的值: " +redisTemplate.opsForList().range("LL2", 0, -1)); //V index(K key, long index); // 根据下表获取列表中的值,下标是从0开始的 System.out.println("获取列表中从某下标开始的值: " + redisTemplate.opsForList().index("LL2",1)); /* Long remove(K key, long count, Object value); 从存储在键中的列表中删除等于值的元素的第一个计数事件。 计数参数以下列方式影响操作: count> 0:删除等于从头到尾移动的值的元素。 count <0:删除等于从尾到头移动的值的元素。 count = 0:删除等于value的所有元素。*/ System.out.println("删除前的值:"+redisTemplate.opsForList().range("LL2", 0, -1)); redisTemplate.opsForList().remove("LL2",1,"b1"); System.out.println("删除列表中存储的列表中第一次出现的“b1”:"+redisTemplate.opsForList().range("LL2", 0, -1)); redisTemplate.opsForList().remove("LL2",0,"b2"); System.out.println("删除列表中指定的“b2”:"+redisTemplate.opsForList().range("LL2", 0, -1));
修改指定的位置的值: [b3, pop, b2, b1]
获取列表中从某下标开始的值: pop
删除前的值:[b3, pop, b2, b1]
删除列表中存储的列表中第一次出现的“b1”:[b3, pop, b2]
删除列表中指定的“b2”:[b3, pop]
3)
/* V leftPop(K key); 弹出最左边的元素,弹出之后该值在列表中将不复存在*/ System.out.println("弹出前的值:"+ redisTemplate.opsForList().range("LL2", 0, -1));
redisTemplate.opsForList().leftPop("LL2"); System.out.println("弹出后的值:"+redisTemplate.opsForList().range("LL2", 0, -1)); /* V rightPop(K key, long timeout, TimeUnit unit); 移出并获取列表的最后一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。 */
弹出前的值:[b3, pop]
弹出后的值:[pop]
3.redis的hash数据结构
Redis的散列可以让用户将多个键值对存储到一个Redis键里面。
public interface HashOperations<H,HK,HV>
HashOperations提供一系列方法操作hash:
redisTemplate.opsForHash().put("redishash","name","lanpo"); redisTemplate.opsForHash().put("redishash","age","20"); redisTemplate.opsForHash().put("redishash","sex","1"); redisTemplate.opsForHash().put("redishash","qq","2323322"); //放入整个map Map<String, String> map = new HashMap<>(); map.put("name","lupo"); map.put("age","23"); map.put("sex","0"); redisTemplate.opsForHash().putAll("redishash2",map); /* Long delete(H key, Object... hashKeys); 删除给定的哈希hashKeys*/ redisTemplate.opsForHash().delete("redishash","qq"); System.out.println("redishash删除后的值:"+redisTemplate.opsForHash().entries("redishash")); /*Boolean hasKey(H key, Object hashKey); 确定哈希hashKey是否存在*/ System.out.println("是否存在name: "+redisTemplate.opsForHash().hasKey("redishash","name")); System.out.println("是否存在ttt: "+ redisTemplate.opsForHash().hasKey("redishash","ttt")); /* HV get(H key, Object hashKey); 从键中的哈希获取给定hashKey的值*/ System.out.println("从redishash获取age: "+redisTemplate.opsForHash().get("redishash","age"));
redishash删除后的值:{name=lanpo, age=20, sex=1}
是否存在name: true
是否存在ttt: false
从redishash获取age: 20
4.redis的set数据结构
Redis的Set是string类型的无序集合。
集合成员是唯一的,这就意味着集合中不能出现重复的数据。
Redis 中 集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。
public interface SetOperations<K,V>
SetOperations提供了对无序集合的一系列操作:
1)
/* Long add(K key, V... values); 无序集合中添加元素,返回添加个数 也可以直接在add里面添加多个值 如: template.opsForSet().add("setTest","aaa","bbb")*/ redisTemplate.opsForSet().add("set1", "lan", "po", "zui", "ai", "rou"); redisTemplate.opsForSet().add("set2", "lu", "po", "ai", "he", "lanpo"); /* Long remove(K key, Object... values); 移除集合中一个或多个成员:移除rou */ System.out.println("移除后长度:" + redisTemplate.opsForSet().remove("set1", "rou")); /*Boolean isMember(K key, Object o); 判断 member 元素是否是集合 key 的成员*/ System.out.println("lan是否是set1的成员:" +redisTemplate.opsForSet().isMember("set1", "lan")); System.out.println("ttt是否是set1的成员:" + redisTemplate.opsForSet().isMember("set1", "ttt")); /* Set<V> intersect(K key, K otherKey); key对应的无序集合与otherKey对应的无序集合求交集*/ System.out.println("set1的元素:" + redisTemplate.opsForSet().members("set1")); System.out.println("set2的元素:" + redisTemplate.opsForSet().members("set2")); System.out.println("两个集合的交集:" + redisTemplate.opsForSet().intersect("set1", "set2"));
移除长度:1 lan是否是set1的成员:true ttt是否是set1的成员:false set1的元素:[ai, lan, po, zui] set2的元素:[lu, he, lanpo, ai, po] 两个集合的交集:[ai, po]
2)
/*Long intersectAndStore(K key, K otherKey, K destKey); key无序集合与otherkey无序集合的交集 存储到destKey无序集合中*/ redisTemplate.opsForSet().intersectAndStore("set1", "set2", "setplus"); System.out.println("交集setplus的元素:" + redisTemplate.opsForSet().members("setplus")); /*Set<V> union(K key, K otherKey); key无序集合与otherKey无序集合的并集*/ System.out.println("set1的元素:" + redisTemplate.opsForSet().members("set1")); System.out.println("set2的元素:" + redisTemplate.opsForSet().members("set2")); System.out.println("set1和set2的并集:" + redisTemplate.opsForSet().union("set1", "set2")); /* Set<V> union(K key, Collection<K> otherKeys); key无序集合与多个otherKey无序集合的并集:略 */ /*Long unionAndStore(K key, K otherKey, K destKey); key无序集合与otherkey无序集合的并集 存储到destKey无序集合中*/ redisTemplate.opsForSet().unionAndStore("set1","set2","setpo"); System.out.println("并集后的结果setpo:" + redisTemplate.opsForSet().members("setpo"));
交集setplus的元素:[ai, po]
set1的元素:[ai, po, zui, lan]
set2的元素:[po, ai, lanpo, lu, he]
set1和set2的并集:[lan, lu, lanpo, po, zui, ai, he]
并集后的结果setpo:[lanpo, zui, po, he, lu, ai, lan]
3)
/* Set<V> difference(K key, K otherKey); key无序集合与otherKey无序集合的差集*/ System.out.println("set1的元素:" + redisTemplate.opsForSet().members("set1")); System.out.println("set2的元素:" + redisTemplate.opsForSet().members("set2")); System.out.println("两个差集:" + redisTemplate.opsForSet().difference("set1","set2")); /* V randomMember(K key); 随机获取key无序集合中的一个元素*/ System.out.println("随机获取到set1的元素:" + redisTemplate.opsForSet().randomMember("set1")); System.out.println("随机获取到set1的元素:" + redisTemplate.opsForSet().randomMember("set1")); System.out.println("随机获取到set1的元素:" + redisTemplate.opsForSet().randomMember("set1")); System.out.println("随机获取到set1的元素:" + redisTemplate.opsForSet().randomMember("set1")); System.out.println("随机获取到set1的元素:" + redisTemplate.opsForSet().randomMember("set1")); /* Set<V> distinctRandomMembers(K key, long count); 获取多个key无序集合中的元素(去重),count表示个数*/ System.out.println("随机获取到set1的2个元素:" + redisTemplate.opsForSet().randomMembers("set1",2)); System.out.println("随机获取到set1的2个元素:" + redisTemplate.opsForSet().randomMembers("set1",2)); System.out.println("随机获取到set1的2个元素:" + redisTemplate.opsForSet().randomMembers("set1",2)); System.out.println("随机获取到set1的2个元素:" + redisTemplate.opsForSet().randomMembers("set1",2)); /*Cursor<V> scan(K key, ScanOptions options); 遍历set*/ Cursor<String> cursor = redisTemplate.opsForSet().scan("set1", ScanOptions.NONE); while (cursor.hasNext()){ System.out.println(cursor.next()); }
set1的元素:[lan, ai, po, zui]
set2的元素:[po, ai, lu, lanpo, he]
两个差集:[lan, zui]
随机获取到set1的元素:ai
随机获取到set1的元素:zui
随机获取到set1的元素:lan
随机获取到set1的元素:zui
随机获取到set1的元素:po
随机获取到set1的2个元素:[po, po]
随机获取到set1的2个元素:[ai, lan]
随机获取到set1的2个元素:[zui, lan]
随机获取到set1的2个元素:[lan, po]
5.redis的zset数据结构
Redis 有序集合和无序集合一样也是string类型元素的集合,且不允许重复的成员。
不同的是每个元素都会关联一个double类型的分数。
redis正是通过分数来为集合中的成员进行从小到大的排序。
有序集合的成员是唯一的,但分数(score)却可以重复。
public interface ZSetOperations<K,V>
ZSetOperations提供了一系列方法对有序集合进行操作:
6. opsForHyperLogLog();
HyperLogLog是Redis中的高级数据结构,它主要用于对海量数据(可以统计2^64个数据)
做基数统计(去重统计数量)。它的特点是速度快,占用空间小(12KB)。
但是计算存会在误差,标准误差为0.81%。HyperLogLog只会根据输入元素来计算基数,
而不会储存输入元素本身,所以他并不能判断给定的元素是否已经存在了。
参考文章
浙公网安备 33010602011771号