文章目录
Redis五大数据类型
字符串(String)
-
注意:
字符串的值实际不局限于字符串,比如普通的字符串,复杂的字符串如JSON,XML,数字,甚至二进制都可以,但不能超过512MB下面,我们来演示增删改查的基本操作
SET key value
GET key
DEL key
MSET key1 value1 key2 value2 … keyN valueN --同时设置一个或多个 key-value 对
MGET KEY1 KEY2 … KEYN – 返回所有(一个或多个)给定 key 的值
Flushdb:清空
哈希(hash)
-
在Redis中,哈希类型是指键值本身又是一个键值对结构。
我们依然围绕增删改查:
hSet key filed value
Hget key field
hgetall key --获取key中所有的属性
Hdel key field
列表(List)
-
Redis中的列表类型是用来存储多个有序的字符串,且可重复。底层是双向链表
增删改查
LPUSH key value [value …],向左边添加元素
LRANGE key start stop,查询列表元素 0 -1 表示查询列表的所有元素
RPUSH key value [value …],向右边添加元素
LPOP key,弹出左边的元素
RPOP key,弹出右边的元素
LREM KEY_NAME COUNT VALUE ,根据参数 COUNT 的值,移除列表中与参数 VALUE 相等的元素
其他命令:
LLEN key,查询列表的长度
LINDEX key index,获取指定索引的值 get(int index)
LSET key index value,设置指定索引的值
集合(Set)
-
Redis中的集合也是用来保存多个的字符串元素,不同的是,集合不允许有重复的元素,并且集合中的元素是无序的。底层是一个hash表
常用命令:set
Sadd key element [element] 添加元素
Scard key 计算元素个数
Smembers key 获取所有的元素
Srem key element [element] 删除元素
Sismember key element 判断元素是否在集合中,存在返回1,否则返回0
Spop key 从集合随机弹出元素
有序集合(ZSet)
-
Redis中的有序集合是一种特殊的集合,首先,他不允许集合中存在重复元素,其次它是有序的,但这个有序的实现方式不同于我们前面讲到的列表,他是基于分数来进行排序的。
zset
常用命令:
Zadd key score member [score member …] 添加成员,并为每个成员设置分数
Zrange key 0 -1
应用场景:
排行榜系统
Spring操作五大数据类型
- Spring整合Redis后给每种类型都提供了一个类来操作Redis。
@Test
public void testOpration() {
// 1.操作字符串
ValueOperations valueOperations = redisTemplate.opsForValue();
valueOperations.set("name","admin");
System.out.println("字符串:"+valueOperations.get("name"));
// 2.操作哈希
HashOperations hashOperations = redisTemplate.opsForHash();
Map<String,Object> stuMap = new HashMap<String, Object>();
stuMap.put("name","张三");
stuMap.put("age",10);
hashOperations.putAll("student",stuMap); // 用hash存对象
System.out.println(hashOperations.get("student","age"));
// 3.操作链表
ListOperations listOperations = redisTemplate.opsForList();
listOperations.leftPushAll("books","Java","Spring","MyBatis");
List books = listOperations.range("books", 0, -1);
System.out.println(books);
// 4.操作无序集合
SetOperations setOperations = redisTemplate.opsForSet();
setOperations.add("emails","zs@qf.com","ls@qf.com","ww@qf.com");
System.out.println(setOperations.members("emails"));
// 5.操作有序集合
ZSetOperations zSetOperations = redisTemplate.opsForZSet();
zSetOperations.add("score","zs",10);
zSetOperations.add("score","ls",20);
zSetOperations.add("score","ww",15);
System.out.println(zSetOperations.range("score",0,-1));
}
事务管理
Redis事务特点
-
redis的事务是使用multi-exec的命令组合,使用它可以提供两个重要保证:
1、事务是一个被隔离的操作,事务中的方法都会被redis进行序列化并按顺序执行,事务在执行的过程中不会被其他客户端的发出的命令所打断。2、事务是一个原子性操作,它要么全部执行、要么全部不执行。
multi到exec命令之间的Redis命令将采取进入队列的形式,直至exec命令的出现,才会一次性发送队列的命令去执行。
基本事务的命令
- Multi:开启事务,之后的命令就会进入队列,而不是马上执行
Exec:提交事务,如果被监听的键没有被修改,则采用提交命令,否则就执行回滚命令
Discard:回滚事务
watch key1 [key2]…:监听某些键,当被监听的键在提交事务前被修改,则事务会回滚 (基于乐观锁机制)
unwatch :取消监听
事务基本操作
Redis中,执行格式错误的命令,会导致事务无法提交。
乐观锁机制
- 一个事务对某个属性设置监听,开启事务后对这个属性进行操作,如果在此期间有其他事务对该属性进行了修改,那最后这个事务是执行失败的。
SpringBoot操作Redis事务
@Test
public void testRedisTransaction(){
try{
// 1.开启事务
redisTemplate.multi();
// 2.操作redis
redisTemplate.opsForValue().set("name","admin");
redisTemplate.opsForValue().set("age",12);
// 3.事务提交
redisTemplate.exec();
}catch (Exception e){
// 4.出现异常事务回滚
redisTemplate.discard();
e.printStackTrace();
}
}
-
该程序执行完后会出现如下异常:
异常信息说的是:事务回滚的时候没有开启事务,就是事务开启和事务回滚没有在一个redis连接里面进行。解决方案如下:
@Test
public void testRedisTransaction2(){
redisTemplate.execute(new SessionCallback() {
@Nullable // 标识参数可以为空
@Override
public Object execute(RedisOperations redisOperations) throws DataAccessException {
try{
// 1.开启事务
redisTemplate.multi();
// 2.操作redis
redisTemplate.opsForValue().set("name","admin");
redisTemplate.opsForValue().set("age",12);
// 3.事务提交
List list = redisTemplate.exec();
System.out.println(list);
}catch (Exception e){
// 4.出现异常事务回滚
redisTemplate.discard();
e.printStackTrace();
}
return null;
}
});
- 用execte这个方法操作Redis,就可以保证在匿名类中的所有的操作用的是同一个Redis连接对象。
流水线(pipelined)
- 在现实情况中,redis的读写速度十分快,而系统的瓶颈往往是在网络通信中的延迟。redis可能会在很多时候处于空闲状态而等待命令的到达。为了解决这个问题,可以使用redis的流水线,流水线是一种通讯协议,类似一个队列批量执行一组命令。
- 来一段性能的测试做对比:
1,没有使用流水线技术的写法
2,使用流水线的写法