文章目录
Reids存储的是key-value结构的数据类型,value有5中常用的数据类型:
1.字符串string,常用
2.哈希hash,hash适合存储对象
3.列表list,按照插入顺序排序,可以有重复元素
4.集合set,无序集合,没有重复元素
5.有序集合sorted set,有序集合,没有重复元素
字符串string类型操作命令
SET key value 设置指定key的值
GET key 获取指定key的值
SETEX key seconds value 设置指定key的值,并将key的过期时间设为seconds秒
SETNX key value 只有在key不存在时设置key的值
哈希hash操作命令
Redis hash是一个string类型的field和value的映射表,hash特别适合用于存储对象,常用命令:
HASH key field value 将哈希表key中的字段field的值设为value
HASH key field 获取存储在哈希表中指定字段的值
HDEL key field 删除存储在哈希表中的指定字段
HKEYS key 获取哈希表中所有字段
HVALS key 获取哈希表中所有值
HGETALL key 获取在hash表中指定key的所有字段和值
列表list操作命令
Redis列表是简单的字符串列表,按照插入顺序排序,常用命令:
LPUSH key value1 [value2] 将一个或多个值插入到列表头部(LPUSH可以看成从左边插入)
LRANGE key start stop 获取列表指定范围内的元素(LRANGE可以看成从左边开始数)
RPOP key 移除并获取列表最后一个元素(RPOP可以看成删除并获取最右边的value)
LLEN key 获取列表长度
BRPOP key1 [key2] timeout 移除并获取列表最后一个元素,如果列表没有元素会阻塞列表直接直到等待超时
或发现可弹出元素位置
集合set操作命令
Redis set是string类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据,常用命令:
SADD key member1 [member2] 向集合中添加一个或多个成员
SMEMBERS key 获取集合中的所有成员
SCARD key 获取集合中的成员数
SINTER key1 [key2] 返回给定所有集合中的交集
SUNION key1 [key2] 返回给定所有集合中的并集
SDIFF key1 [key2] 返回给定所有集合中的差集
SREM key member1 [member2] 移除集合中一个或多个成员
有序集合zset操作命令
Redis zxet有序集合是string类型元素的集合,且不允许重复的成员。每个元素都会关联一个double类型的分数(score)。Redis正是通过分数来为集合中的成员进行从小到大排序。有序集合的成员是唯一的,但分数却可以重复。
ZADD key score1 member1 [score2 member2] 向有序集合中添加一个或多个成员,或者更新已存在成员的分数
ZRANGE key start stop [WITHSCORES] 通过索引区间返回有序集合中指定区间内的成员
ZINCRBY key increment member 有序集合中对指定成员的分数加上增量increment
ZREM key member [member] 移除有序集合中的一个或多个成员
新数据类型
BitMaps
本身是一个字符串,不是数据类型,数组的每个单元只能存放0和1,数组的下标在Bitmaps叫做偏移量。
节省空间,一般存储活跃用户比较多。
第一次初始化bitmaps,如果偏移量比较大,那么整个初始化过程执行会比较慢,还可能会造成redis的堵塞。
setbit key offset value 设置Bitmaps中某个偏移量的值(0或1) 偏移量从0开始
getbit key offset 获取Bitmaps中某个偏移量的值
bitcount key (start end) 统计字符串从start到end字节比特值为1的数量
(一个字节是8位,例如bitcount user 1 2,就是从第一个字节到第二个字节,
换成偏移量是第8位到22位中1的个数)
bitop and(or/not/xor) destkey key[key...] 复合操作,交并非异或,结果保存到destkey
HyperLogLog
基数:例如{1,3,5,7,9,1,3},基数集是:{1,3,5,7,9},基数是5。
1.统计网页中页面访问量。
2.只会根据输入元素来计算基数,而不会储存输入元素本身,不能像集合那样,返回输入的各个元素。
3.基数估计是在误差可接受的范围内,快速计算(不重复元素的结算)。
pfadd key element [element...] 添加指定元素到hyperloglog中
pfcount key 计算key的近似基数
pfmerge destkey sourcekey sourcekey 一个或多个key合并后的结果存在另一个key
Geographic
提供经纬度设置,查询范围,距离查询等。
geoadd key longitude latitude member [longitude latitude member...] 添加地理位置(经纬度名称)
geopos key member 获取指定地区的坐标值
geodist key member1 member2 (m km ft mi)获取两个位置的直线距离(m米,km千米,mi英里,ft英尺,默认m)
georadius key longitude latitude radius (m km ft mi)以给定的经纬度为中心,找出某一半径内的元素
通用命令
KEYS pattern 查看所有符合给定模式(pattern)的key
EXISTS key 检查给定key是否存在
TYPE key 返回key所存储值的类型
TTL key 返回给定key的剩余生存时间(TTL,time to live),以秒为单位
DEL key 该命令用在key存在时删除key
使用Spring Data Redis操作Redis
导入maven坐标
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
Spring Data Redis中提供了一个高度封装的类:RedisTemplate,针对jedis客户端中大量API进行了归类封装,将统一类型操作封装为operation接口,具体分类如下:
ValueOperations:简单K-V操作
SetOperations:set类型数据操作
ZSetOperations:zset类型数据操作
HashOperations:针对map类型数据操作
ListOperations:针对list类型的数据操作
配置:
redis:
host: localhost
port: 6379
database: 0 #操作的是0号数据库,不写的话默认是0号数据库
jedis:
#Redis连接池配置
pool:
max-active: 16 #最大连接数
max-wait: 1ms #连接池最大连接阻塞时间
max-idle: 5 #连接池中最大空闲连接
min-idle: 0 #连接池中最小空闲连接
配置Redis配置类RedisConfig:
@Configuration
@EnableCaching //启用缓存
public class RedisCacheConfig extends CachingConfigurerSupport{
@Bean
public RedisTemplate redisTemplate(RedisConnectionFactory factory){
RedisTemplate redisTemplate = new RedisTemplate();
redisTemplate.setConnectionFactory(factory);
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
redisTemplate.setKeySerializer(stringRedisSerializer);
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.setHashKeySerializer(stringRedisSerializer);
redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
}
例子:
@Autowired
private RedisTemplate redisTemplate;
/**
* 操作String类型数据
*/
@Test
public void testString() {
redisTemplate.opsForValue().set("city123","beijing");
String value = (String) redisTemplate.opsForValue().get("city123");
System.out.println(value);
//设置key-value,10s后过期
redisTemplate.opsForValue().set("key1","value1",10l, TimeUnit.MICROSECONDS);
//只有在key不存在时设置key的值 判断key是否存在,存在则返回false;不存在返回true并设置key的值
Boolean aBoolean = redisTemplate.opsForValue().setIfAbsent("city123", "nanjing");
System.out.println(aBoolean);
}
/**
* 操作Hash类型数据
*/
@Test
public void testHash(){
HashOperations hashOperations = redisTemplate.opsForHash();
//存值
hashOperations.put("002","name","xiaoming");
hashOperations.put("002","age","18");
hashOperations.put("002","address","wuhan");
//取值
String name = (String) hashOperations.get("002", "name");
System.out.println(name);
//获得hash结构中的所有字段
Set keys = hashOperations.keys("002");
for (Object key:keys){
System.out.println(key);
}
//获取hash结构中的所有值
List values = hashOperations.values("002");
for (Object value:values){
System.out.println(value);
}
}
/**
* 操作list类型的数据
*/
@Test
void testList() {
ListOperations listOperations = redisTemplate.opsForList();
//存值
listOperations.leftPush("mylist","a");
listOperations.leftPushAll("mylist","b","c","d");
//取值
List<String> mylist = listOperations.range("mylist", 0, -1);
for (String value:mylist){
System.out.println(value);
}
//获得队列长度llen
Long size = listOperations.size("mylist");
int intValue = size.intValue();
for (int i = 0; i < intValue; i++) {
//出队列
String rightPop = (String) listOperations.rightPop("mylist");
System.out.println(rightPop);
}
}
/**
* 操作set类型的数据
*/
@Test
public void testSet() {
SetOperations setOperations = redisTemplate.opsForSet();
//存值
setOperations.add("myset","a","b","c","d");
//取值
Set<String> myset = setOperations.members("myset");
for (String o : myset) {
System.out.println(o);
}
//删除成员
setOperations.remove("myset","a","b");
}
/**
* 操作ZSet类型的数据
*/
@Test
public void testZSet() {
ZSetOperations zSetOperations = redisTemplate.opsForZSet();
//存值
zSetOperations.add("myZset","a",10.0);
zSetOperations.add("myZset","b",11.0);
zSetOperations.add("myZset","c",12.0);
zSetOperations.add("myZset","a",13.0);
//取值
Set<String> myzset = zSetOperations.range("myZset", 0, -1);
for (String s : myzset) {
System.out.println(s);
}
//修改分数
zSetOperations.incrementScore("myZset","a",20.0);
//删除成员
zSetOperations.remove("myZset","a");
zSetOperations.remove("myZset","b");
}
/**
* 通用操作
*/
@Test
public void testCommon(){
//获取Redis中所有的key
Set keys = redisTemplate.keys("*");
for (Object key : keys) {
System.out.println(key);
}
//判断某个key是否存在
Boolean hasKey = redisTemplate.hasKey("myset");
System.out.println(hasKey);
//删除指定key
redisTemplate.delete("myset");
//获取指定key对应的value的数据类型
DataType dataType = redisTemplate.type("myZset");
System.out.println(dataType.name());
}
事务操作
- 单独的隔离操作
- 事务中的所有命令都会序列化
- 按顺序执行
- 执行的过程中,不会被其他命令请求所打断
Redis事务三大特性
单独的隔离操作:事务中的所有命令都会序列化、按顺序执行。事务在执行过程中,不会被其他客户端发送来的命令请求所打断。
没有隔离级别:队列中的命令没有提交之前都不会实际被执行,因为事务事务提交前任何指令都不会别实际执行。
不保证原子性:事务中如果有一条命令执行失败,其后的命令仍然会被执行,不会回滚。
sql的事务特性,为acid,一致性,隔离性,原子性,持久性。
Redis事务的主要作用是串联多个命令防止别的命令插队。
三个主要命令:
multi 组队阶段,还未执行
exec 执行阶段,将multi的队列放到exec中
discard 放弃multi在队列中的值
从输入multi命令开始,输入的命令都会进入命令队列中,但不会执行,直到输入exec后,Redis会将之前的命令队列中的命令一次执行。
组队的过程中可以通过discard来放弃组队。
事务的错误处理:组队的时候失败,则执行的时候也会失败,所有命令都不会成功;
组队的时候成功,执行时出错,那么出错指令执行失败,其他命令会成功;
悲观锁和乐观锁
悲观锁:不能同时进行操作,对数据执行操作前会上锁,防止其他人操作。
乐观锁:给数据加上版本,同步更新数据及版本号,可以多人操作。每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。
命令:
watch key1 [key2...] 乐观锁,在执行multi之前,先执行watch可以监视一个或多个key,
如果在事务执行之前key被其他命令所改动,那么事务将被打断。
flushdb 清空数据库