Redis


Redis

概述

  1. 基于内存的key-value数据库

  2. 基于c语言编写的,可以支持多种语言的api //set每秒11万次,取get 81000次

  3. 支持数据持久化

  4. value可以是string,hash, list, set, sorted set

  5. 应用场景

基本服务器管理

  1. 使用redis客户端连接redis本机服务:
    [root@CentOs bin]# ./redis-cli

  2. 使用redis客户端连接redis远程服务(使用本机模拟):
    [root@CentOs bin]# ./redis-cli -h 192.168.25.128 -p 6379

  3. 健康检查命令:
    192.168.25.128:6379> ping
    PONG

  4. 重启redis服务:
    [root@CentOs bin]# ./redis-server redis.conf

  5. 使用redis客户端关闭redis服务
    [root@CentOs bin]# ./redis-cli shutdown

  6. 重启redis服务:
    [root@CentOs bin]# ./redis-server redis.conf

Redis的五种数据类型

对于Redis 来说,他只能存储五种基本数据类型

在之前的版本中都是String,Hash,List,SortedSet(zSet),Map

而现在的新版本中String,Hash,List,SortedSet(zSet),Set

一、字符串String —–String Key-Value

  字符串是Redis中最常用的类型,是一个由字节组成的序列,他在Redis中是二进制安全的

这意味着该类型可以接受任何格式的数据。

Value最多可以容纳的数据长度为512MB

set key value

往key 中存入一个值(value)

获取键为key的值

  注意:redis中的Key和Value时区分大小写,命令不区分大小写,redis是单线程不适合储存大容量的数据

自增的value是可以转成数字的

二、散列Hash——key-filed-value

  相当于是一个key中存在多个map.Redis中的散列可以看成具有String key和String value的map

容器,可以将多个key-value存储到一个key钟。每一个Hash可以存储4294967295个键值对。

三、集合Set

  Redis的集合是无序不可重复的,此处的无序是数据不能重复。和列表一样,在执行插入和删除

以及判断是否存在某元素时,效率是很高的。集合最大的优势在于可以进行交集并集,差集操作。

Set可包含的最大元素数量是4294967295.

  应用场景:1.利用交集求共同好友。2.利用唯一性,可以统计访问网站的所有独立Ip。

3.好友推荐的时候根据tag求交集,大于某个threshold(临界值)就可以推荐。

四、列表List

  Redis的列表允许用户从序列的两端推入或者弹出元素,列表有多个字符串值组成的有序可重复的序列,

是链表结构,所以向列表两端添加元素的时间复杂度为O(1),获取越接近两端的元素速度就越

快。这意味着即使是一个有几千万个元素的列表,获取头部活尾部的10条记录也是极快的。List中可以

包含最大的元素数量是4294967295.

五、SortedSet(zSet)

  有顺序,不能重复!!此处的不能重复是索引为唯一的,数据却可以重复。和Set很像

都是字符串的集合,都不允许重复的成员出现在一个Set中。他们之间差别在于有序集合中每一个成员都会有一个

分数与之关联,Redis正是通过分数来为集合中的成员进行从小到大的排序。尽管有序集合中的

成员必须是唯一的,但是分数却可以重复。

  应用场景:可以用于一个大型的在线游戏的积分排行榜,每当玩家的分数发生变化是,可以执行zadd

更新玩家的分数,此后在通过zrange获取积分top n的用户信息

数据库键空间

Redis是一个键值对(key-value pair)数据库服务器,服务器中的每个数据库都由一个redisDb结构表示,其中,redisDb结构的dict字典保存了数据库中的所有键值对,我们将这个字典称为键空间(key space)

键空间和用户所见的数据库是直接对应的

键空间的键也就是数据库的键,每个键都是一个字符串对象
键空间的值也就是数据库的值,每个值可以是字符串对象、列表对象、哈希表对象、集合对象和有序集合对象中的任意一种Redis对象

读写键空间的维护操作

  • 当使用Redis命令对数据库进行读写时,服务器不仅会对键空间执行指定读写操作,还会执行一些额外的维护操作

  • 在读取一个键之后(包括读操作和写操作),服务器会根据键是否存在,来更新服务器的键命中和不命中次数,可以通过INFO stats 命令的 keyspace_hits 属性和 keyspace_misses 属性查看

  • 在读取一个键之后,服务器会更新键的LRU(最后一次使用时间),这个值可以用于计算键的限制时间,使用OBJECT idletime < key > 命令查看

  • 如果服务器在读取一个键时发现该键已经过期,那么服务器会先删除这个过期键,然后才执行余下的其他操作

  • 如果有客户端使用WATCH命令监视某个key,那么服务器在对被监视的键进行修改之后,会将这个键标记为脏,从而让事务程序注意到这个键已经被修改过

  • 服务器每次修改一个键之后,都会对脏键计数器的值增1,这个计数器会触发服务器的持久化以及复制操作(例如自动BGSAVE操作,就是查看在多少时间内对键进行了多少次修改,达到设定值则进行RDB持久化)

  • 如果服务器开启了数据库通知功能,那么在对键进行修改之后,服务器将按配置发送相应的数据库通知。

Redis的数据的基本操作

1.set str1 abc:添加键str1,其值为:abc
2.get str1:得到键为str1的值
3.incr key1:key1加1,如果key1不存在,自动创建一个key1的键,其值为0,加一,key1的值为1
4.keys * :显示所有的key
5.decr key1:key1减一
    说明:不论是incr还是decr,保存的数据都是字符串,执行incr或decr命令时候,把字符串转换为整数,再进行加减,
           如果转换失败,则报错
6.del key1:删除键和值

7.hset hash1 field1 1:键为Hash1,值为hash,键为field1,值为1
    同一个hash中可以放入多个值,如:
        hset hash1 field2 2
        hset hash1 field3 3
8.hget hash1 field1:取hash1中field1的值
9.hkeys hash1:查看hash1的所有键
10.hvals hash1:查看hash1的所有值
11.hgetall hash1:查看hash1的所有键和值
12.hdel hash1 field1:删除hash1的field1
以下了解:
13.lpush list1 1 2 3 4 5 6:从左边压入,后压入的在最左边
14.rpush list1 a b c d:从右边压入,后压入的在最右边
15.lrange list1 0 -1:查看list1 的范围值,0表示第一个元素索引,-1表示所有
16.lpop list1:从list1左边取出第一个元素(相当于出栈,取出后,list1中移除该元素)
17.rpop list1:从list1右边取出第一个元素(相当于出栈)

18.sadd set1 a b a b d c:向set1中添加一个set,值为a b a b d c(会去掉重复的元素)
19.srem set1 a:从set1中移除一个元素a(可以一次移除多个元素)
20.smembers set1:显示set1中的元素
21:集合相减:
    sadd seta a b c d e 
    sadd setb c d e f g 
    sdiff seta setb :seta - setb =>a b
    sdiff setb seta :setb - seta => f g
22.sinter seta setb :seta和setb的交集=》a b c
23.sunion seta setb:seta 和set的并集合=》a b c d e f g

24.zadd zset1 1 a 3 b 2 c 5 d :向zset1中添加元素,并且根据分数(权重)排序
25.zrange zset1 0 -1:查看zset1中的所有元素(排序后的结果)
26.zrem zset1 a:删除zset1中的a元素
27.zrevrange zset1 0 -1:降序排序输出
28.zrevrange zset1 0 -1 withscores:降序排序输出,并输出权重

29.expire key1 100:设置key1的过期时间为100秒(key1必须先存在,没有设置过期时间,就是永久保存的)
30.ttl key1:查看key1的剩余过期时间
    值为整数:表示该键正在过期倒计时
    值为-2:表示该键已经过期(不存在的)
    值为-1:表示该键永久保存,已经持久化了
31.persist key1:持久化key1(设置了过期时间后,还没有到过期时间的时候使用)

设置键的生存时间或过期时间

通过 EXPIRE 命令或者 PEXPIRE 命令,客户端可以以秒或者毫秒精度为数据库中的某个键设置生存时间(Time To Live,TTL),在经过指定的秒数或者毫秒数之后,服务器就会自动删除生存时间为0的键

Time命令返回值是一个包含两个字符串的列表: 第一个字符串是当前时间(以 UNIX 时间戳格式表示),而第二个字符串是当前这一秒钟已经逝去的微秒数

1秒=1000毫秒(ms), 1毫秒=1/1000秒(s);
1秒=1000000 微秒(μs), 1微秒=1/1000000秒(s);
1秒=1000000000 纳秒(ns),1纳秒=1/1000000000秒(s);
1秒=1000000000000皮秒 1皮秒==1/1000000000000秒。

通过 EXPIREATPEXPIREAT 命令,可以设定一个时间戳,该过期时间是一个UNIX时间戳,当键的过期时间来临时,服务器就会自动从数据库中删除这个键,可以通过TIME命令查看UNIX的时间

TTL命令和PTTL命令接受一个带有生存时间或者过期时间的键,返回这个键的剩余生存时间,也就是,返回距离这个键被服务器自动删除还有多长时间

设置过期时间

通过上面的例子,可以看出Redis有四个不同的命令可以用于设置键的生存时间(键可以存在多久)或过期时间(键什么时候会被删除)

  • EXPIRE<key><ttl>命令用于将键key的生存时间设置为ttl
  • PEXPIRE<key><ttl>命令用于将键key的生存时间设置为ttl毫秒
  • EXPIREAT<key><timestamp>命令用于将键key的过期时间设置为timestamp所指定的秒数时间戳
  • PEXPIREAT<key><timestamp>命令用于将键key的过期时间设置为timestamp所指定的毫秒数时间戳

虽然有多种不同单位和不同形式的设置命令,但实际上EXPIRE、PEXPIRE、EXPIREAT三个命令都是使用PEXPIREAT命令来实现的

保存过期时间

redisDb结构的expires字典保存了数据库中所有键的过期时间,我们称这个字典为过期字典

过期字典的键是一个指针,这个指针指向键空间中的某个键对象(也即是某个数据库键)
过期字典的值是一个long long类型的整数,这个整数保存了键所指向的数据库键的过期时间——一个毫秒精度的UNIX时间戳

移除过期时间

PERSIST命令可以移除一个键的过期时间

PERSIST命令就是PEXPIREAT命令的反操作:PERSIST命令在过期字典中查找给定的键,并解除键和值(过期时间)在过期字典中的关联

计算并返回剩余时间和过期键的判定

计算并返回剩余生存时间

TTL命令以秒为单位返回键的剩余生存时间,而PTTL命令则以毫秒为单位返回键的剩余生存时间。这两个命令都是通过计算键的过期时间和当前时间之间的差来实现的

过期键的判定

通过过期字典,程序可以用以下步骤检查一个给定键是否过期

  • 检查给定键是否存在于过期字典
    • 如果存在,那么取得键的过期时间
  • 检查当前UNIX时间戳是否大于键的过期时间
    • 是的话,那么键已经过期
    • 不是的话,键未过期

redis的持久化

  1. Redis的所有数据都是保存到内存中的。
    1)Rdb:快照形式,定期把内存中当前时刻的数据保存到磁盘。Redis默认支持的持久化方案。
    2)aof形式:append only file。把所有对redis数据库操作的命令,增删改操作的命令。保存到文件中。数据库恢复时把所有的命令执行一遍即可。

  2. 查看redis.conf文件
    1)rdb形式:(看redis.conf中的注释说明)
    save 900 1 //15分钟有一次变化,则保存
    save 300 10 //5分钟有10次变化,保存
    save 60 10000 //在60秒中有10000次变化了,则保存一次
    2)开启aof形式:
    修改appendonly no为appendonly yes即可
    a)修改后,使用客户端关闭redis服务
    ./redis-cli shutdown
    b)重启redis服务
    ./redis-server redis.conf
    c)开启服务后,在bin目录中多了一个文件:appendonly.aof
    d)添加几个key,测试,在查看appendonly.aof文件大小和内容变化(cat appendonly.aof)

RedisTemplate

Jedis

Jedis是Redis官方推出的一款面向Java的客户端,提供了很多接口供Java语言调用。可以在Redis官网下载,当然还有一些开源爱好者提供的客户端,如Jredis、SRP等等,推荐使用Jedis。

Spring Data Redis

Spring-data-redis是spring大家族的一部分,提供了在srping应用中通过简单的配置访问redis服务,对reids底层开发包(Jedis, JRedis, and RJC)进行了高度封装,RedisTemplate提供了redis各种操作、异常处理及序列化,支持发布订阅,并对spring 3.1 cache进行了实现。

spring-data-redis针对jedis提供了如下功能:

  1. 连接池自动管理,提供了一个高度封装的“RedisTemplate”类
  2. 针对jedis客户端中大量api进行了归类封装,将同一类型操作封装为operation接口
  • ValueOperations:简单K-V操作
  • SetOperations:set类型数据操作
  • ZSetOperations:zset类型数据操作
  • HashOperations:针对map类型的数据操作
  • ListOperations:针对list类型的数据操作
  1. 提供了对key的“bound”(绑定)便捷化操作API,可以通过bound封装指定的key,然后进行一系列的操作而无须“显式”的再次指定Key,即BoundKeyOperations:
  • BoundValueOperations
  • BoundSetOperations
  • BoundListOperations
  • BoundSetOperations
  • BoundHashOperations
  1. 将事务操作封装,有容器控制。

  2. 针对数据的“序列化/反序列化”,提供了多种可选择策略(RedisSerializer)

    • JdkSerializationRedisSerializer:POJO对象的存取场景,使用JDK本身序列化机制,将pojo类通过ObjectInputStream/ObjectOutputStream进行序列化操作,最终redis-server中将存储字节序列。是目前最常用的序列化策略。

      • StringRedisSerializer:Key或者value为字符串的场景,根据指定的charset对数据的字节序列编码成string,是“new String(bytes, charset)”和“string.getBytes(charset)”的直接封装。是最轻量级和高效的策略。

      • JacksonJsonRedisSerializer:jackson-json工具提供了javabean与json之间的转换能力,可以将pojo实例序列化成json格式存储在redis中,也可以将json格式的数据转换成pojo实例。因为jackson工具在序列化和反序列化时,需要明确指定Class类型,因此此策略封装起来稍微复杂。【需要jackson-mapper-asl工具支持】

使用

1、pom.xml依赖

<!--Redis-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

2、配置文件

# Redis服务器连接端口
spring.redis.port=6379
# Redis服务器地址
spring.redis.host=127.0.0.1
# Redis数据库索引(默认为0)
spring.redis.database=0
# Redis服务器连接密码(默认为空)
spring.redis.password=
# 连接池最大连接数(使用负值表示没有限制)
spring.redis.jedis.pool.max-active=8
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.jedis.pool.max-wait=-1ms
# 连接池中的最大空闲连接
spring.redis.jedis.pool.max-idle=8
# 连接池中的最小空闲连接
spring.redis.jedis.pool.min-idle=0
# 连接超时时间(毫秒)
spring.redis.timeout=5000ms

3、RedisTemplate的直接方法

首先使用@Autowired注入RedisTemplate(后面直接使用,就不特殊说明)

@Autowired
private RedisTemplate redisTemplate;

1、删除单个key

//    删除key
public void delete(String key)&#123;
    redisTemplate.delete(key);
&#125;

2、删除多个key

//    删除多个key
public void deleteKey (String ...keys)&#123;
    redisTemplate.delete(keys);
&#125;

3、指定key的失效时间

//    指定key的失效时间
public void expire(String key,long time)&#123;
    redisTemplate.expire(key,time,TimeUnit.MINUTES);
&#125;

4、根据key获取过期时间

//    根据key获取过期时间
public long getExpire(String key)&#123;
    Long expire = redisTemplate.getExpire(key);
    return expire;
&#125;

5、判断key是否存在

//    判断key是否存在
public boolean hasKey(String key)&#123;
    return redisTemplate.hasKey(key);
&#125;

4、String类型相关操作

1)、添加缓存
//1、通过redisTemplate设置值
redisTemplate.boundValueOps("StringKey").set("StringValue");
redisTemplate.boundValueOps("StringKey").set("StringValue",1, TimeUnit.MINUTES);

//2、通过BoundValueOperations设置值
BoundValueOperations stringKey = redisTemplate.boundValueOps("StringKey");
stringKey.set("StringVaule");
stringKey.set("StringValue",1, TimeUnit.MINUTES);

//3、通过ValueOperations设置值
ValueOperations ops = redisTemplate.opsForValue();
ops.set("StringKey", "StringVaule");
ops.set("StringValue","StringVaule",1, TimeUnit.MINUTES);
2)、设置过期时间(单独设置)
redisTemplate.boundValueOps("StringKey").expire(1,TimeUnit.MINUTES);
redisTemplate.expire("StringKey",1,TimeUnit.MINUTES);
3)、获取缓存值
//1、通过redisTemplate设置值
String str1 = (String) redisTemplate.boundValueOps("StringKey").get();

//2、通过BoundValueOperations获取值
BoundValueOperations stringKey = redisTemplate.boundValueOps("StringKey");
String str2 = (String) stringKey.get();

//3、通过ValueOperations获取值
ValueOperations ops = redisTemplate.opsForValue();
String str3 = (String) ops.get("StringKey");
4)、删除key
Boolean result = redisTemplate.delete("StringKey");
5)、顺序递增
redisTemplate.boundValueOps("StringKey").increment(3L);
6)、顺序递减
redisTemplate.boundValueOps("StringKey").increment(-3L);

5、Hash类型相关操作

1)、添加缓存
//1、通过redisTemplate设置值
redisTemplate.boundHashOps("HashKey").put("SmallKey", "HashVaue");

//2、通过BoundValueOperations设置值
BoundHashOperations hashKey = redisTemplate.boundHashOps("HashKey");
hashKey.put("SmallKey", "HashVaue");

//3、通过ValueOperations设置值
HashOperations hashOps = redisTemplate.opsForHash();
hashOps.put("HashKey", "SmallKey", "HashVaue");
2)、设置过期时间(单独设置)
redisTemplate.boundValueOps("HashKey").expire(1,TimeUnit.MINUTES);
redisTemplate.expire("HashKey",1,TimeUnit.MINUTES);
3)、添加一个Map集合
HashMap<String, String> hashMap = new HashMap<>();
redisTemplate.boundHashOps("HashKey").putAll(hashMap );
4)、设置过期时间(单独设置)
redisTemplate.boundValueOps("HashKey").expire(1,TimeUnit.MINUTES);
redisTemplate.expire("HashKey",1,TimeUnit.MINUTES);
5)、提取所有的key
//1、通过redisTemplate获取值
Set keys1 = redisTemplate.boundHashOps("HashKey").keys();

//2、通过BoundValueOperations获取值
BoundHashOperations hashKey = redisTemplate.boundHashOps("HashKey");
Set keys2 = hashKey.keys();

//3、通过ValueOperations获取值
HashOperations hashOps = redisTemplate.opsForHash();
Set keys3 = hashOps.keys("HashKey");
6)、提取所有的value值
//1、通过redisTemplate获取值
List values1 = redisTemplate.boundHashOps("HashKey").values();

//2、通过BoundValueOperations获取值
BoundHashOperations hashKey = redisTemplate.boundHashOps("HashKey");
List values2 = hashKey.values();

//3、通过ValueOperations获取值
HashOperations hashOps = redisTemplate.opsForHash();
List values3 = hashOps.values("HashKey");
7)、根据key提取value值
//1、通过redisTemplate获取
String value1 = (String) redisTemplate.boundHashOps("HashKey").get("SmallKey");

//2、通过BoundValueOperations获取值
BoundHashOperations hashKey = redisTemplate.boundHashOps("HashKey");
String value2 = (String) hashKey.get("SmallKey");

//3、通过ValueOperations获取值
HashOperations hashOps = redisTemplate.opsForHash();
String value3 = (String) hashOps.get("HashKey", "SmallKey");
8)、获取所有的键值对集合
//1、通过redisTemplate获取
Map entries = redisTemplate.boundHashOps("HashKey").entries();

//2、通过BoundValueOperations获取值
BoundHashOperations hashKey = redisTemplate.boundHashOps("HashKey");
Map entries1 = hashKey.entries();

//3、通过ValueOperations获取值
HashOperations hashOps = redisTemplate.opsForHash();
Map entries2 = hashOps.entries("HashKey");
9)、删除
//删除小key
redisTemplate.boundHashOps("HashKey").delete("SmallKey");
//删除大key
redisTemplate.delete("HashKey");
10)、判断Hash中是否含有该值
Boolean isEmpty = redisTemplate.boundHashOps("HashKey").hasKey("SmallKey");

6、Set类型相关操作

1)、添加Set缓存(值可以是一个,也可是多个)
//1、通过redisTemplate设置值
redisTemplate.boundSetOps("setKey").add("setValue1", "setValue2", "setValue3");

//2、通过BoundValueOperations设置值
BoundSetOperations setKey = redisTemplate.boundSetOps("setKey");
setKey.add("setValue1", "setValue2", "setValue3");

//3、通过ValueOperations设置值
SetOperations setOps = redisTemplate.opsForSet();
setOps.add("setKey", "SetValue1", "setValue2", "setValue3");
2)、设置过期时间(单独设置)
redisTemplate.boundValueOps("setKey").expire(1,TimeUnit.MINUTES);
redisTemplate.expire("setKey",1,TimeUnit.MINUTES);
12
3)、根据key获取Set中的所有值
//1、通过redisTemplate获取值
Set set1 = redisTemplate.boundSetOps("setKey").members();

//2、通过BoundValueOperations获取值
BoundSetOperations setKey = redisTemplate.boundSetOps("setKey");
Set set2 = setKey.members();

//3、通过ValueOperations获取值
SetOperations setOps = redisTemplate.opsForSet();
Set set3 = setOps.members("setKey");
12345678910
4)、根据value从一个set中查询,是否存在
Boolean isEmpty = redisTemplate.boundSetOps("setKey").isMember("setValue2");
1
5)、获取Set缓存的长度
Long size = redisTemplate.boundSetOps("setKey").size();
1
6)、移除指定的元素
Long result1 = redisTemplate.boundSetOps("setKey").remove("setValue1");
1
7)、移除指定的key
Boolean result2 = redisTemplate.delete("setKey");
1

7、 LIST类型相关操作

1)、添加缓存(2/3是1的递进值)
//1、通过redisTemplate设置值
redisTemplate.boundListOps("listKey").leftPush("listLeftValue1");
redisTemplate.boundListOps("listKey").rightPush("listRightValue2");

//2、通过BoundValueOperations设置值
BoundListOperations listKey = redisTemplate.boundListOps("listKey");
listKey.leftPush("listLeftValue3");
listKey.rightPush("listRightValue4");

//3、通过ValueOperations设置值
ListOperations opsList = redisTemplate.opsForList();
opsList.leftPush("listKey", "listLeftValue5");
opsList.rightPush("listKey", "listRightValue6");
2)、将List放入缓存
ArrayList<String> list = new ArrayList<>();
redisTemplate.boundListOps("listKey").rightPushAll(list);
redisTemplate.boundListOps("listKey").leftPushAll(list);
3)、设置过期时间(单独设置)
redisTemplate.boundValueOps("listKey").expire(1,TimeUnit.MINUTES);
redisTemplate.expire("listKey",1,TimeUnit.MINUTES);
4)、获取List缓存全部内容(起始索引,结束索引)
List listKey1 = redisTemplate.boundListOps("listKey").range(0, 10); 
5)、从左或从右弹出一个元素
String listKey2 = (String) redisTemplate.boundListOps("listKey").leftPop();  //从左侧弹出一个元素
String listKey3 = (String) redisTemplate.boundListOps("listKey").rightPop(); //从右侧弹出一个元素
6)、根据索引查询元素
String listKey4 = (String) redisTemplate.boundListOps("listKey").index(1);
7)、获取List缓存的长度
Long size = redisTemplate.boundListOps("listKey").size();
8)、根据索引修改List中的某条数据(key,索引,值)
redisTemplate.boundListOps("listKey").set(3L,"listLeftValue3");
9)、移除N个值为value(key,移除个数,值)
redisTemplate.boundListOps("listKey").remove(3L,"value");

8、Zset类型的相关操作

1)、向集合中插入元素,并设置分数
//1、通过redisTemplate设置值
redisTemplate.boundZSetOps("zSetKey").add("zSetVaule", 100D);

//2、通过BoundValueOperations设置值
BoundZSetOperations zSetKey = redisTemplate.boundZSetOps("zSetKey");
zSetKey.add("zSetVaule", 100D);

//3、通过ValueOperations设置值
ZSetOperations zSetOps = redisTemplate.opsForZSet();
zSetOps.add("zSetKey", "zSetVaule", 100D);
2)、向集合中插入多个元素,并设置分数
DefaultTypedTuple<String> p1 = new DefaultTypedTuple<>("zSetVaule1", 2.1D);
DefaultTypedTuple<String> p2 = new DefaultTypedTuple<>("zSetVaule2", 3.3D);
redisTemplate.boundZSetOps("zSetKey").add(new HashSet<>(Arrays.asList(p1,p2)));
3)、按照排名先后(从小到大)打印指定区间内的元素, -1为打印全部
Set<String> range = redisTemplate.boundZSetOps("zSetKey").range(key, 0, -1);
4)、获得指定元素的分数
Double score = redisTemplate.boundZSetOps("zSetKey").score("zSetVaule");
5)、返回集合内的成员个数
Long size = redisTemplate.boundZSetOps("zSetKey").size();
6)、返回集合内指定分数范围的成员个数(Double类型)
Long COUNT = redisTemplate.boundZSetOps("zSetKey").count(0D, 2.2D);
7)、返回集合内元素在指定分数范围内的排名(从小到大)
Set byScore = redisTemplate.boundZSetOps("zSetKey").rangeByScore(0D, 2.2D);
8)、带偏移量和个数,(key,起始分数,最大分数,偏移量,个数)
Set<String> ranking2 = redisTemplate.opsForZSet().rangeByScore("zSetKey", 0D, 2.2D 1, 3);
9)、返回集合内元素的排名,以及分数(从小到大)
Set<TypedTuple<String>> tuples = redisTemplate.boundZSetOps("zSetKey").rangeWithScores(0L, 3L);
  for (TypedTuple<String> tuple : tuples) &#123;
      System.out.println(tuple.getValue() + " : " + tuple.getScore());
  &#125;ss
10)、返回指定成员的排名
//从小到大
Long startRank = redisTemplate.boundZSetOps("zSetKey").rank("zSetVaule");
//从大到小
Long endRank = redisTemplate.boundZSetOps("zSetKey").reverseRank("zSetVaule");
11)、从集合中删除指定元素
redisTemplate.boundZSetOps("zSetKey").remove("zSetVaule");
12)、删除指定索引范围的元素(Long类型)
redisTemplate.boundZSetOps("zSetKey").removeRange(0L,3L);
13)、删除指定分数范围内的元素(Double类型)
redisTemplate.boundZSetOps("zSetKey").removeRangeByScorssse(0D,2.2D);
14)、为指定元素加分(Double类型)
Double score = redisTemplate.boundZSetOps("zSetKey").incrementScore("zSetVaule",1.1D);

配置 RedisTemplate

修改 RedisTemplate 中键和值的序列化方式(默认key的序列化方式是:JdkSerializationRedisSerializer)

package com.neu.springdemo;

import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SetOperations;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
 
@Configuration
@EnableCaching //开启注解
public class RedisConfig extends CachingConfigurerSupport { 
    /**
     * retemplate相关配置
     */
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
 
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        // 配置连接工厂
        template.setConnectionFactory(factory);
 
        //使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值(默认使用JDK的序列化方式)
        Jackson2JsonRedisSerializer<Object> jacksonSeial = new Jackson2JsonRedisSerializer<>(Object.class);
 
        ObjectMapper om = new ObjectMapper();
        // 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        // 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会跑出异常
        om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);
        jacksonSeial.setObjectMapper(om);
 
        // 值采用json序列化
        template.setValueSerializer(jacksonSeial);
        //使用StringRedisSerializer来序列化和反序列化redis的key值
        template.setKeySerializer(new StringRedisSerializer());
 
        // 设置hash key 和value序列化模式
        template.setHashKeySerializer(new StringRedisSerializer());
        template.setHashValueSerializer(jacksonSeial);
        template.afterPropertiesSet();
 
        return template;
    }
}

Redis 缓存工具类

package com.neu.springdemo;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundSetOperations;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;

/**
 * spring redis 工具类
 * 
 * @author ruoyi
 **/
@SuppressWarnings(value = { "unchecked", "rawtypes" })
@Component
public class RedisCache
{
    @Autowired
    public RedisTemplate redisTemplate;

    /**
     * 缓存基本的对象,Integer、String、实体类等
     *
     * @param key 缓存的键值
     * @param value 缓存的值
     * @return 缓存的对象
     */
    public <T> ValueOperations<String, T> setCacheObject(String key, T value)
    {
        ValueOperations<String, T> operation = redisTemplate.opsForValue();
        operation.set(key, value);
        return operation;
    }

    /**
     * 缓存基本的对象,Integer、String、实体类等
     *
     * @param key 缓存的键值
     * @param value 缓存的值
     * @param timeout 时间
     * @param timeUnit 时间颗粒度
     * @return 缓存的对象
     */
    public <T> ValueOperations<String, T> setCacheObject(String key, T value, Integer timeout, TimeUnit timeUnit)
    {
        ValueOperations<String, T> operation = redisTemplate.opsForValue();
        operation.set(key, value, timeout, timeUnit);
        return operation;
    }

    /**
     * 获得缓存的基本对象。
     *
     * @param key 缓存键值
     * @return 缓存键值对应的数据
     */
    public <T> T getCacheObject(String key)
    {
        ValueOperations<String, T> operation = redisTemplate.opsForValue();
        return operation.get(key);
    }

    /**
     * 删除单个对象
     *
     * @param key
     */
    public void deleteObject(String key)
    {
        redisTemplate.delete(key);
    }

    /**
     * 删除集合对象
     *
     * @param collection
     */
    public void deleteObject(Collection collection)
    {
        redisTemplate.delete(collection);
    }

    /**
     * 缓存List数据
     *
     * @param key 缓存的键值
     * @param dataList 待缓存的List数据
     * @return 缓存的对象
     */
    public <T> ListOperations<String, T> setCacheList(String key, List<T> dataList)
    {
        ListOperations listOperation = redisTemplate.opsForList();
        if (null != dataList)
        {
            int size = dataList.size();
            for (int i = 0; i < size; i++)
            {
                listOperation.leftPush(key, dataList.get(i));
            }
        }
        return listOperation;
    }

    /**
     * 获得缓存的list对象
     *
     * @param key 缓存的键值
     * @return 缓存键值对应的数据
     */
    public <T> List<T> getCacheList(String key)
    {
        List<T> dataList = new ArrayList<T>();
        ListOperations<String, T> listOperation = redisTemplate.opsForList();
        Long size = listOperation.size(key);

        for (int i = 0; i < size; i++)
        {
            dataList.add(listOperation.index(key, i));
        }
        return dataList;
    }

    /**
     * 缓存Set
     *
     * @param key 缓存键值
     * @param dataSet 缓存的数据
     * @return 缓存数据的对象
     */
    public <T> BoundSetOperations<String, T> setCacheSet(String key, Set<T> dataSet)
    {
        BoundSetOperations<String, T> setOperation = redisTemplate.boundSetOps(key);
        Iterator<T> it = dataSet.iterator();
        while (it.hasNext())
        {
            setOperation.add(it.next());
        }
        return setOperation;
    }

    /**
     * 获得缓存的set
     *
     * @param key
     * @return
     */
    public <T> Set<T> getCacheSet(String key)
    {
        Set<T> dataSet = new HashSet<T>();
        BoundSetOperations<String, T> operation = redisTemplate.boundSetOps(key);
        dataSet = operation.members();
        return dataSet;
    }

    /**
     * 缓存Map
     *
     * @param key
     * @param dataMap
     * @return
     */
    public <T> HashOperations<String, String, T> setCacheMap(String key, Map<String, T> dataMap)
    {
        HashOperations hashOperations = redisTemplate.opsForHash();
        if (null != dataMap)
        {
            for (Map.Entry<String, T> entry : dataMap.entrySet())
            {
                hashOperations.put(key, entry.getKey(), entry.getValue());
            }
        }
        return hashOperations;
    }

    /**
     * 获得缓存的Map
     *
     * @param key
     * @return
     */
    public <T> Map<String, T> getCacheMap(String key)
    {
        Map<String, T> map = redisTemplate.opsForHash().entries(key);
        return map;
    }

    /**
     * 获得缓存的基本对象列表
     * 
     * @param pattern 字符串前缀
     * @return 对象列表
     */
    public Collection<String> keys(String pattern)
    {
        return redisTemplate.keys(pattern);
    }
}

测试类

package com.neu.springdemo;

import java.util.Date;

import javax.annotation.Resource;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;

@SpringBootTest
class SpringdemoRedisDemo1ApplicationTests {

    @Autowired
    private RedisCache redisCache;

    @Test
    void contextLoads() {		
        Student stu = new Student();
        stu.setAge(18);
        stu.setId(10);
        stu.setName("marry");
        stu.setBirthday(new Date());
        
        //缓存对象
        redisCache.setCacheObject("stu3", stu);
        //得到缓存对象
        Student stu3 = redisCache.getCacheObject("stu3");
        System.out.println(stu3);
    }

}

命令附录

key

keys * 获取所有的key
select 0 选择第一个库
move myString 1 将当前的数据库key移动到某个数据库,目标库有,则不能移动
flush db 清除指定库
randomkey 随机key
type key 类型
set key1 value1 设置key
get key1 获取key
mset key1 value1 key2 value2 key3 value3
mget key1 key2 key3
del key1 删除key
exists key 判断是否存在key
expire key 10 10秒过期
pexpire key 1000 毫秒
persist key 删除过期时间

TTL key 获取key的过期时间。

​ 如果key存在过期时间,返回剩余生存时间(秒);如果key是永久的,返回-1;如果key不存在或者已过期,返回-2

string

​ set name cxx
​ get name
​ getrange name 0 -1 字符串分段
​ getset name new_cxx 设置值,返回旧值
​ mset key1 key2 批量设置
​ mget key1 key2 批量获取
​ setnx key value 不存在就插入(not exists)
​ setex key time value 过期时间(expire)
​ setrange key index value 从index开始替换value
​ incr age 递增
​ incrby age 10 递增
​ decr age 递减
​ decrby age 10 递减
​ incrbyfloat 增减浮点数
​ append 追加
​ strlen 长度
​ getbit/setbit/bitcount/bitop 位操作

hash

​ hset myhash name cxx
​ hget myhash name
​ hmset myhash name cxx age 25 note “i am notes”
​ hmget myhash name age note
​ hgetall myhash 获取所有的
​ hexists myhash name 是否存在
​ hsetnx myhash score 100 设置不存在的
​ hincrby myhash id 1 递增
​ hdel myhash name 删除
​ hkeys myhash 只取key
​ hvals myhash 只取value
​ hlen myhash 长度

list

​ lpush mylist a b c 左插入
​ rpush mylist x y z 右插入
​ lrange mylist 0 -1 数据集合(查询)
​ lpop mylist 弹出元素
​ rpop mylist 弹出元素
​ llen mylist 长度
​ lrem mylist count value 删除
​ lindex mylist 2 指定索引的值
​ lset mylist 2 n 索引设值
​ ltrim mylist 0 4 删除key
​ linsert mylist before a 插入
​ linsert mylist after a 插入
​ rpoplpush list list2 转移列表的数据

set

​ sadd myset redis
​ smembers myset 数据集合
​ srem myset set1 删除
​ sismember myset set1 判断元素是否在集合中
​ scard key_name 个数
​ sdiff | sinter | sunion 操作:集合间运算:差集 | 交集 | 并集
​ srandmember 随机获取集合中的元素
​ spop 从集合中弹出一个元素

zset

​ zadd zset 1 one
​ zadd zset 2 two
​ zadd zset 3 three
​ zincrby zset 1 one 增长分数
​ zscore zset two 获取分数
​ zrange zset 0 -1 withscores 范围值
​ zrangebyscore zset 10 25 withscores 指定范围的值
​ zrangebyscore zset 10 25 withscores limit 1 2 分页
​ Zrevrangebyscore zset 10 25 withscores 指定范围的值
​ zcard zset 元素数量
​ Zcount zset 获得指定分数范围内的元素个数
​ Zrem zset one two 删除一个或多个元素
​ Zremrangebyrank zset 0 1 按照排名范围删除元素
​ Zremrangebyscore zset 0 1 按照分数范围删除元素
​ Zrank zset 0 -1 分数最小的元素排名为0
​ Zrevrank zset 0 -1 分数最大的元素排名为0
​ Zinterstore
​ zunionstore rank:last_week 7 rank:20150323 rank:20150324 rank:20150325 weights 1 1 1 1 1 1 1

排序

​ sort mylist 排序
​ sort mylist alpha desc limit 0 2 字母排序
​ sort list by it:* desc by命令
​ sort list by it:* desc get it:* get参数
​ sort list by it:* desc get it:* store sorc:result sort命令之store参数:表示把sort查询的结果集保存起来

订阅与发布

​ 订阅频道:subscribe chat1
​ 发布消息:publish chat1 “hell0 ni hao”
​ 查看频道:pubsub channels
​ 查看某个频道的订阅者数量: pubsub numsub chat1
​ 退订指定频道: unsubscrible chat1 , punsubscribe java.*
​ 订阅一组频道: psubscribe java.*

redis事务

​ 隔离性,原子性,
​ 步骤: 开始事务,执行命令,提交事务
​ multi //开启事务
​ sadd myset a b c
​ sadd myset e f g
​ lpush mylist aa bb cc
​ lpush mylist dd ff gg

​ exec //提交事务


文章作者: FFFfrance
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 FFFfrance !