1.Redis key值操作以及RedisTemplate对应的API
本文默认使用RedisTemplate,关于RedisTemplate和StringRedisTemplate的区别如下

复制代码
RedisTemplate和StringRedisTemplate
二者主要区别是他们使用的序列化类不一样,RedisTemplate使用的是JdkSerializationRedisSerializer,
StringRedisTemplate使用的是StringRedisSerializer,两者的数据是不共通的。

1.RedisTemplate:
RedisTemplate使用的是JDK的序列化策略,向Redis存入数据会将数据先序列化成字节数组然后在存入Redis数据库,这个时候打开Redis查看的时候,
你会看到你的数据不是以可读的形式展现的,而是以字节数组显示,类似下面:\xAC\xED\x00\x05t\x05sr\x00。
所以使用RedisTemplate可以直接把一个java对象直接存储在redis里面。

2.StringRedisTemplate:
StringRedisTemplate默认采用的是String的序列化策略,保存的key和value都是采用此策略序列化保存的。
StringRedisTemplate是继承RedisTemplate的,这种对redis的操方式更优雅,
因为RedisTemplate以字节数组的形式存储不利于管理,也不通用。

如果存入的是简单的字符串使用StringRedisTemplate;

如果存入的是复杂的对象用RedisTemplate;

复制代码
1.1 Key操作
1.1.1 常用的key操作
keys *查看当前库所有key (匹配:keys *1)

public Set keys(String pattern) {
  return redisTemplate.keys(pattern);
}
exists key判断某个key是否存在

public Boolean hasKey(String key) {
return redisTemplate.hasKey(key);
}
type key 查看你的key是什么类型

public DataType type(String key) {
return redisTemplate.type(key);
}
del key 删除指定的key数据

public void delete(String key) {
redisTemplate.delete(key);
}
unlink key 根据value选择非阻塞删除,仅将keys从keyspace元数据中删除,真正的删除会在后续异步操作。

public void unlink(String key) {
redisTemplate.unlink(key);
}
expire key 10 10秒钟:为给定的key设置过期时间

public Boolean expire(String key, long timeout, TimeUnit unit) {
return redisTemplate.expire(key, timeout, unit);
}
ttl key 查看还有多少秒过期,-1表示永不过期,-2表示已过期

public Long getExpire(String key) {
return redisTemplate.getExpire(key);
}
复制代码
flushdb 清空当前库

public void flushdb() {
Set keys = redisTemplate.keys("*");
redisTemplate.delete(keys);
}
复制代码
复制代码
dbsize 查看当前数据库的key的数量

// 令pattern = “*”
public Set keys(String pattern) {
return redisTemplate.keys(pattern);
}
复制代码
2.Redis 五大数据类型操作以及RedisTemplate对应的API
2.1 String类型
String是Redis最基本的类型,你可以理解成与Memcached一模一样的类型,一个key对应一个value。String类型是二进制安全的。意味着Redis的string可以包含任何数据。比如jpg图片或者序列化的对象。String类型是Redis最基本的数据类型,一个Redis中字符串value最多可以是512M。
应用场景
复制代码
1.缓存结构体信息:
将结构体json序列化成字符串,然后将字符串保存在redis的value中,将结构体的业务唯一标示作为key;这种保存json的用法用的最多的场景就是缓存用户信息,
将用户bean信息转成json再序列化为字符串作为value保存在redis中,将用户id作为key。从代码中获取用户缓存信息就是一个逆过程,
根据userid作为key获取到结构体json,然后将json转成java bean。

2.计数功能:
我们都知道redis是单线程模式,并且redis将很多常用的事务操作进行了封装,这里我们最常用的就是数值自增或自减,redis的作者封装了incr可以进行自增,
没调用一次自增1,因为redis是单线程运行,所以就算client是多线程调用那么也是正确自增,因为incr命令中将read和write做了事务封装。
同样可以设置incr的step,每次根据step进行自增,当然如果要达到自减的效果,那么只要将step设置为负数就可以了。
计数功能使用的场景很多,我们之前经常用在实时计数统计场景,也用在过库存场景、限流计数场景等等,而且redis的性能也是非常高的,
对于一般的并发量没那么高的系统都是适用的。
复制代码
2.1.1 String的数据结构
String的数据结构为简单动态字符串(Simple Dynamic String,缩写SDS)。是可以修改的字符串,内部结构实现上类似于Java的ArrayList,采用预分配冗余空间的方式来减少内存的频繁分配.

如上图中所示,内部为当前字符串实际分配的空间capacity一般要高于实际字符串长度len。当字符串长度小于1M时,扩容都是加倍现有的空间,如果超过1M,扩容时一次只会多扩1M的空间。需要注意的是字符串最大长度为512M。

2.1.2 String常用指令
set 添加键值对

public void set(String key, String value) {
redisTemplate.opsForValue().set(key, value);
}
set … nx:当数据库中key不存在时,可以将key-value添加数据库

public boolean setIfAbsent(String key, String value) {
return redisTemplate.opsForValue().setIfAbsent(key, value);
}
set … xx:当数据库中key存在时,可以将key-value添加数据库,与nx参数互斥

public boolean setIfPresent(String key, String value) {
return redisTemplate.opsForValue().setIfPresent(key, value);
}
复制代码
set … ex:设置key的超时秒数
set … px:设置key的超时毫秒数

public void setEx(String key, String value, long timeout, TimeUnit unit) {
redisTemplate.opsForValue().set(key, value, timeout, unit);
}
复制代码
get 查询对应键值

public Object get(String key) {
return redisTemplate.opsForValue().get(key);
}
append 将给定的 追加到原值的末尾

public Integer append(String key, String value) {
return redisTemplate.opsForValue().append(key, value);
}
strlen 获得值的长度

public Long size(String key) {
return redisTemplate.opsForValue().size(key);
}
复制代码
incr 将 key 中储存的数字值增1,只能对数字值操作,如果为空,新增值为1
decr 将 key 中储存的数字值减1,只能对数字值操作,如果为空,新增值为-1
incrby / decrby <步长>将 key 中储存的数字值增减。自定义步长。

public Long incrBy(String key, long increment) {
return redisTemplate.opsForValue().increment(key, increment);
}
复制代码
mset … 同时设置一个或多个 key-value对

public void multiSet(Map<String, String> maps) {
redisTemplate.opsForValue().multiSet(maps);
}
mget … 同时获取一个或多个 value

public List multiSet(Collection keys) {
return redisTemplate.opsForValue().multiGet(keys);
}
复制代码
msetnx … 同时设置一个或多个 key-value 对,当且仅当所有给定 key 都不存在。原子性,有一个失败则都失败

public boolean multiSetIfAbsent(Map<String, String> maps) {
return redisTemplate.opsForValue().multiSetIfAbsent(maps);
}
复制代码
getrange <起始位置><结束位置>获得值的范围,类似java中的substring,前包,后包

public Object getRange(String key, long start, long end) {
return redisTemplate.opsForValue().get(key, start, end);
}
setrange <起始位置> 用 覆写所储存的字符串值,从<起始位置>开始(索引从0开始)。

public void setRange(String key, String value, long offset) {
redisTemplate.opsForValue().set(key, value, offset);
}
getset 以新换旧,设置了新值同时获得旧值。

public Object getAndSet(String key, String value) {
return redisTemplate.opsForValue().getAndSet(key, value);
}
2.2 List类型
Redis 列表List类型是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。它的底层实际是个双向链表,对两端的操作性能很高,通过索引下标的操作中间的节点性能会较差。

应用场景

复制代码
1.list列表结构常用来做异步队列使用
将需要延后处理的任务结构体序列化成字符串塞进 Redis 的列表,另一个线程从这个列表中轮询数据进行处理。

2.list可用于秒杀抢购场景
在商品秒杀场景最怕的就是商品超卖,为了解决超卖问题,我们经常会将库存商品缓存到类似MQ的队列中,多线程的购买请求都是从队列中取,
取完了就卖完了,但是用MQ处理的化有点重,这里就可以使用redis的list数据类型来实现,在秒杀前将本场秒杀的商品放到list中,
因为list的pop操作是原子性的,所以即使有多个用户同时请求,也是依次pop,list空了pop抛出异常就代表商品卖完了。
复制代码
2.2.1 List的数据结构
List的数据结构为快速链表quickList。首先在列表元素较少的情况下会使用一块连续的内存存储,这个结构是ziplist,也即是压缩列表。它将所有的元素紧挨着一起存储,分配的是一块连续的内存。当数据量比较多的时候才会改成quicklist。因为普通的链表需要的附加指针空间太大,会比较浪费空间。比如这个列表里存的只是int类型的数据,结构上还需要两个额外的指针prev和next。

Redis将链表和ziplist结合起来组成了quicklist。也就是将多个ziplist使用双向指针串起来使用。这样既满足了快速的插入删除性能,又不会出现太大的空间冗余。

2.2.2 List常用的指令
复制代码
lpush/rpush … 从左边/右边插入一个或多个值。

public Long lLeftPush(String key, String value) {
return redisTemplate.opsForList().leftPush(key, value);
}

public Long lLeftPushAll(String key, String… value) {
return redisTemplate.opsForList().leftPushAll(key, value);
}

public Long lLeftPushAll(String key, Collection value) {
return redisTemplate.opsForList().leftPushAll(key, value);
}
复制代码
lpop/rpop 从左边/右边吐出一个值。值在键在,值光键亡。

public Object lLeftPop(String key) {
return redisTemplate.opsForList().leftPop(key);
}
rpoplpush 从列表右边吐出一个值,插到列表左边。

public Object lRightPopAndLeftPush(String sourceKey, String destinationKey) {
return redisTemplate.opsForList().rightPopAndLeftPush(sourceKey, destinationKey);
}
复制代码
lrange 按照索引下标获得元素(从左到右)

lrange 0 -1 0左边第一个,-1右边第一个,(0-1表示获取所有)

public List lRange(String key, long start, long end) {
return redisTemplate.opsForList().range(key, start, end);
}
复制代码
lindex 按照索引下标获得元素(从左到右)

public Object lIndex(String key, long index) {
return redisTemplate.opsForList().index(key, index);
}
llen 获得列表长度

public Long lLen(String key) {
return redisTemplate.opsForList().size(key);
}
lset将列表key下标为index的值替换成value

public void lSet(String key, long index, String value) {
redisTemplate.opsForList().set(key, index, value);
}
linsert before 在的前面插入插入值

public Long lLeftPush(String key, String pivot, String value) {
return redisTemplate.opsForList().leftPush(key, pivot, value);
}
lrem n>0 从左边到右删除n个value, n<0从右到左删除n个value

public Long lRemove(String key, long index, String value) {
return redisTemplate.opsForList().remove(key, index, value);
}
USB Microphone https://www.soft-voice.com/
Wooden Speakers https://www.zeshuiplatform.com/
亚马逊测评 www.yisuping.cn
深圳网站建设www.sz886.com

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐