文章目录
Redis
一、Redis常用命令
1. Redis常用命令
- KEYS:查看复合模版的所有key,不建议在生产环境设备上使用
- DEL:删除一个指定的key
- EXISTS:判断key是否存在
- EXPIRE:给一个key设置有效期,有效期到期时该key会被自动删除
- TTL:查看一个key的剩余有效期
2. String类型常见命令
String类型,也就是字符串类型,是Redis中最简单的存储类型,其value是字符串,不过根据字符串的格式不同,又可以分为3类
- string:普通字符串
- int:整数类型,可以做自增、自减操作
- float:浮点类型,可以做自增、自减操作
String的常见命令有:
- SET:添加或者修改已经存在的一个String类型的键值对
- GET:根据key获取String类型的value
- MSET:批量添加多个String类型的键值对
- MGET:根据多个key获取多个String类型的value
- INCR:让一个整型的key自增1
- INCRBY:让一个整型的key自增并指定步长,例如INCRBY NUM 2,让num值自增2
- INCRBYFLOAT:让一个浮点类型的数字自增并指定步长
- SETNX:添加一个String类型的键值对,前提是这个key不存在
- SETEX:添加一个String类型的键值对,并且指定有效期
3. Hash类型的常见命令
- HSET:添加或修改hash类型key的field值
- HGET:获取一个hash类型key的field的值
- HMSET:批量添加多个hash类型key的field的值
- HMGET:批量获取多个hash类型key的field的值
- HGETALL:获取一个hash类型的key中的所有的field和value
- HKEYS:获取一个hash类型的key中的所有的field
- HVALS:获取一个hash类型的key中的所有的value
- HINCRBY:让一个hash类型key的字段值自增并指定步长
- HSETNX:添加一个hash类型的key的field值,前提是这个field不存在,否则不执行
4. List类型的常见命令
- LPUSH:向列表左侧插入一个或多个元素
- LPOP:移除并返回列表左侧的第一个元素,没有则返回nil
- RPUSH:向列表右侧插入一个或多个元素
- RPOP:移除并返回列表右侧的第一个元素
- LRANGE:返回一段角标范围内的所有元素
- BLPOP和BRPOP:与LPOP和RPOP类似,只不过在没有元素时等待指定时间,而不是直接返回nil
5. Set类型的常见类型
- SADD:向set中添加一个或多个元素
- SREM:移除set中的指定元素
- SCARD:返回set中元素的个数
- SISMEMBER:判断一个元素是否存在于set中
- SMEMBERS:获取set中的所有元素
- SINTER key1 key2:求key1与key2的交集
- SDIFF key1 key2:求key1与key2的差集
- SUNION key1 key2:求key1与key2的并集
6. SortedSet类型的常见命令
- ZADD:添加一个或多个元素到sorted set,如果已经存在则更新其score值
- ZREM:删除sorted set中的一个指定元素
- ZSCORE:获取sorted set中的指定元素的score值
- ZRANK:获取sorted set中的指定元素的排名
- ZCARD:获取sorted set中的元素个数
- ZCOUNT:统计sorted set值在给定范围内的所有元素的个数
- ZINCRBY:让sorted set中的指定元素自增,步长为指定的increment值
- ZRANGE:按照score排序后,获取指定排名范围内的元素
- ZRANGEBYSCORE:按照score排序后,获取指定score范围内的元素
- ZDIFF、ZINTER、ZUNION:求差集、交集、并集
所有的排名默认都是升序,如果需要降序则在命令的Z后面添加REV即可
二、RedisTemplate的两种序列化方式
1. 为什么要序列化?
RedisTemplate默认使用的序列化器是JdkSerializationRedisSerializer,这会导致存在存入的数据是以字节码的形式存在的
例如,插入字符串:
@Test
void testString(){
//写入一条String
redisTemplate.opsForValue().set("name", "虎哥");
Object name = redisTemplate.opsForValue().get("name");
System.out.println("name = " + name);
}
插入实体类对象
@Test
public void testSaveUser() {
redisTemplate.opsForValue().set("user:100", new User("社会你虎哥", 22));
User o = (User) redisTemplate.opsForValue().get("user:100");
System.out.println("o = " + o);
}
这样的可读性非常差,让人很难理解一条记录的key和value具体是什么,所以我们需要进行序列化。下面介绍两种序列化的方式
2. 序列化的两种方式
1. 自定义RedisTemplate
创建自定义的RedisConfig类,修改RedisTemplate的序列化器为GenericJackson2JsonRedisSerializer
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory){
//创建RedisTemplate对象
RedisTemplate<String, Object> template = new RedisTemplate<>();
//设置连接工厂
template.setConnectionFactory(factory);
//创建json序列化工具
GenericJackson2JsonRedisSerializer jackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
//设置key的序列化
template.setKeySerializer(RedisSerializer.string());
template.setHashKeySerializer(RedisSerializer.string());
//设置value的序列化
template.setValueSerializer(jackson2JsonRedisSerializer);
template.setHashValueSerializer(jackson2JsonRedisSerializer);
//返回
return template;
}
}
修改了RedisTemplate的序列化器后,再次运行上方的两个test,查看效果
存入字符串:
存入实体类对象:
可以看到,再经过了序列化之后,存入的值变成了我们可读的字符串以及json,可读性大大增强。同时也能发现,在将实体类对象序列化后存入Redis中时,也带上了实体类的包名,一两条数据还好,如果有成千上万条数据,这对于内存来说难免是很大的负担,因此我们有没有什么办法可以将实体类的包名不存入Redis中呢,下面看第二种序列化的方法。
2. 使用StringRedisTemplate
在写入Redis时,手动把对象序列化为json;在读取Redis时,手动把读取到的Json反序列化为对象。
这里我们需要添加一个ObjectMapper对象来进行手动的序列化及反序列化。ObjectMapper是jackson中的主要类,一个可以帮助我们快速的对各个类型和Json类型进行相互转换的类。
在使用之前,需要在pom中引用相应的依赖
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.10.2</version>
</dependency>
在引入了依赖后,便可以进行操作。该序列化的方法与上面的方法最大的区别在于我们需要在写入和读取Redis时,手动将对象进行序列化。
写入一个实体类对象
@Test
public void testSaveUser() throws JsonProcessingException {
//创建对象
User user = new User("社会你虎哥", 22);
//手动将存入的对象序列化
String json = mapper.writeValueAsString(user);
stringRedisTemplate.opsForValue().set("user:100", json);
String jsonUser = stringRedisTemplate.opsForValue().get("user:100");
//手动对读取到的数据序列化
User user1 = mapper.readValue(jsonUser, User.class);
System.out.println("user1 = " + user1);
}
可以看到,在进行手动序列化后,存入的数据中实体类的包名消失了,达到了我们的预期。