个人理解
我们都知道 Redis
作为中间缓存的优势之一就是支持多种数据结构,支持的数据结构有:字符串、列表、哈希、集合、有序集合等。
但是我们真正在开发中使用的一般都是字符串类型,即使是自定义对象、数组、Map、Set 等数据结构,我们都可以通过序列化的方式进行存储。
既然字符串类型支持所有数据类型的存储,那其他类型的优点:
(1)序列化总会耗费一些时间,所以我们最好直接存储对应的数据类型。
(2)特殊的数据类型可以参与一些特殊计算,达到特殊的业务需求。
注意:数据结构,是指 Redis
支持的数据结构,不是指 key
,也不是指 value
。
Memcache
与 Redis
的区别:
存储方式
-
Memecache把数据全部存在内存之中,断电后会挂掉,数据不能超过内存大小。
-
Redis有部份存在硬盘上,这样能保证数据的持久性。
数据支持类型
- Memcache对数据类型支持相对简单。
- Redis有复杂的数据类型。
数据类型详解
String(字符串)
存储类型:字符串。
特点:是二进制安全的。意思是可以存储任何数据,比如图片或者序列化的对象。
常用命令:set、get、decr、incr、mget
等。
注意:一个键最大能存储512MB。
Hash(哈希)
存储类型:键值对。
特点:适合用于存储对象。
应用场景:存储一些结构化的数据,比如用户的昵称、年龄、性别等,存储一个用户信息对象数据。
常用命令:hget、hset、hgetall
等。
List(列表)
存储类型:列表数组(数组存放字符串)
特点:
(1)有序,按照插入顺序排序。
(2)添加一个元素到列表的头部(左边)或者尾部(右边)。
应用场景:经常会被用于消息队列的服务,以完成多程序之间的消息交换。
常用命令:lpush、rpush、lpop、rpop、lrange
等。
Set(集合)
存储类型:集合(集合存放字符串)
特点:
(1)无序集合。
(2)不允许重复。
(3)执行插入和删除和判断是否存在某元素时,效率是很高的。
应用场景:
(1)利用交集求共同好友。
(2)利用唯一性,可以统计访问网站的所有独立IP。
(3)好友推荐的时候根据爱好求交集,大于某个临界值的就可以推荐。
常用命令:sadd、spop、smembers、sunion
等。
注意:集合最大的优势在于可以进行交集并集差集操作。
ZSet(有序集合)
存储类型:有序集合(集合存放字符串)
特点:
(1)有序集合。这里的有序不是指插入顺序,是指不同的每个元素都会关联一个分数来进行排序。
(2)不允许重复。
(3)成员是唯一的,但分数却可以重复。
(4)分数是 Double 类型的值。
应用场景:
1、排行榜应用。
2、学生成绩排名。
常用命令:zadd、zrange、zrem、zcard
等。
数据类型命令详解
日常使用中,Java
语言最常见的两种操作 Redis
的方法是:Jedis
和 RedisTemplate
。Jedis
是官方推荐的一种原生方法,而 RedisTemplate
是 Springboot
所封装的方法。
1、Jedis 操作命令
(1)基本操作
exists(key) //确认一个key是否存在
del(key) //删除一个key
type(key) //返回值的类型
keys(pattern) //返回满足给定pattern的所有key
randomkey() //随机返回key空间的一个key
rename(oldname, newname) //将key由oldname重命名为newname,若newname存在则删除newname表示的key
dbsize() //返回当前数据库中key的数目
expire(key, time) //设定一个key的活动时间(s)
ttl(key) //当 key 不存在时,返回 -2 。 当 key 存在但没有设置剩余生存时间时,返回 -1 。 否则,以秒为单位,返回 key 的剩余生存时间。
select(index) //按索引查询
move(key, dbindex) //将当前数据库中的key转移到有dbindex索引的数据库
flushdb() //删除当前选择数据库中的所有key
flushall() //删除所有数据库中的所有key
(2)String(字符串)
set(key, value) //给数据库中名称为key的string赋予值value
get(key) //返回数据库中名称为key的string的value
getset(key, value) //给名称为key的string赋予上一次的value
mget(key1, key2,…, key N) //返回库中多个string(它们的名称为key1,key2…)的value
setnx(key, value) //如果不存在名称为key的string,则向库中添加string,名称为key,值为value
setex(key, time, value) //向库中添加string(名称为key,值为value)同时,设定过期时间time
mset(key1, value1, key2, value2,…key N, value N) //同时给多个string赋值,名称为key i的string赋值value i
msetnx(key1, value1, key2, value2,…key N, value N) //如果所有名称为key i的string都不存在,则向库中添加string,名称key i赋值为value i
incr(key) //名称为key的string增1操作
incrby(key, integer) //名称为key的string增加integer
decr(key) //名称为key的string减1操作
decrby(key, integer) //名称为key的string减少integer
append(key, value) //名称为key的string的值附加value
substr(key, start, end) //返回名称为key的string的value的子串
(3)Hash(哈希)
hset(key, field, value) //向名称为key的hash中添加元素field<—>value
hget(key, field) //返回名称为key的hash中field对应的value
hmget(key, field1, …,field N) //返回名称为key的hash中field i 对应的value
hmset(key, field1, value1,…,field N, value N) //向名称为key的hash中添加元素field i<—>value i
hincrby(key, field, integer) //将名称为key的hash中field的value增加integer
hexists(key, field) //名称为key的hash中是否存在键为field的域
hdel(key, field) //删除名称为key的hash中键为field的域
hlen(key) //返回名称为key的hash中元素个数
hkeys(key) //返回名称为key的hash中所有键
hvals(key) //返回名称为key的hash中所有键对应的value
hgetall(key) //返回名称为key的hash中所有的键(field)及其对应的value
(4)List(列表)
rpush(key, value) //在名称为key的list尾添加一个值为value的元素
lpush(key, value) //在名称为key的list头添加一个值为value的 元素
llen(key) //返回名称为key的list的长度
lrange(key, start, end) //返回名称为key的list中start至end之间的元素(下标从0开始,下同)
ltrim(key, start, end) //截取名称为key的list,保留start至end之间的元素
lindex(key, index) //返回名称为key的list中index位置的元素
lset(key, index, value) //给名称为key的list中index位置的元素赋值为value
lrem(key, count, value) //删除count个名称为key的list中值为value的元素。count为0,删除所有值为value的元素,count>0从头至尾删除count个值为value的元素,count<0从尾到头删除|count|个值为value的元素。
lpop(key) //返回并删除名称为key的list中的首元素
rpop(key) //返回并删除名称为key的list中的尾元素
blpop(key1, key2,… key N, timeout) //lpop命令的block版本。即当timeout为0时,若遇到名称为key i的list不存在或该list为空,则命令结束。如果timeout>0,则遇到上述情况时,等待timeout秒,如果问题没有解决,则对key i+1开始的list执行pop操作。
brpop(key1, key2,… key N, timeout) //rpop的block版本。参考上一命令。
rpoplpush(srckey, dstkey) //返回并删除名称为srckey的list的尾元素,并将该元素添加到名称为dstkey的list的头部
(5)Set(集合)
sadd(key, member) //向名称为key的set中添加元素member
srem(key, member) //删除名称为key的set中的元素member
spop(key) //随机返回并删除名称为key的set中一个元素
smove(srckey, dstkey, member) //将member元素从名称为srckey的集合移到名称为dstkey的集合
scard(key) //返回名称为key的set的基数
sismember(key, member) //测试member是否是名称为key的set的元素
sinter(key1, key2,…key N) //求交集
sinterstore(dstkey, key1, key2,…key N) //求交集并将交集保存到dstkey的集合
sunion(key1, key2,…key N) //求并集
sunionstore(dstkey, key1, key2,…key N) //求并集并将并集保存到dstkey的集合
sdiff(key1, key2,…key N) //求差集
sdiffstore(dstkey, key1, key2,…key N) //求差集并将差集保存到dstkey的集合
smembers(key) //返回名称为key的set的所有元素
srandmember(key) //随机返回名称为key的set的一个元素
(6)ZSet(有序集合)
zadd(key, score, member) //向名称为key的zset中添加元素member,score用于排序。如果该元素已经存在,则根据score更新该元素的顺序。
zrem(key, member) //删除名称为key的zset中的元素member
zincrby(key, increment, member) //如果在名称为key的zset中已经存在元素member,则该元素的score增加increment;否则向集合中添加该元素,其score的值为increment
zrank(key, member) //返回名称为key的zset(元素已按score从小到大排序)中member元素的rank(即index,从0开始),若没有member元素,返回“nil”
zrevrank(key, member) //返回名称为key的zset(元素已按score从大到小排序)中member元素的rank(即index,从0开始),若没有member元素,返回“nil”
zrange(key, start, end) //返回名称为key的zset(元素已按score从小到大排序)中的index从start到end的所有元素
zrevrange(key, start, end) //返回名称为key的zset(元素已按score从大到小排序)中的index从start到end的所有元素
zrangebyscore(key, min, max) //返回名称为key的zset中score >= min且score <= max的所有元素
zcard(key) //返回名称为key的zset的基数
zscore(key, element) //返回名称为key的zset中元素element的score
zremrangebyrank(key, min, max) //删除名称为key的zset中rank >= min且rank <= max的所有元素
zremrangebyscore(key, min, max) //删除名称为key的zset中score >= min且score <= max的所有元素
zunionstore / zinterstore(dstkeyN, key1,…,keyN, WEIGHTS w1,…wN, AGGREGATE SUM|MIN|MAX) //对N个zset求并集和交集,并将最后的集合保存在dstkeyN中。对于集合中每一个元素的score,在进行AGGREGATE运算前,都要乘以对于的WEIGHT参数。如果没有提供WEIGHT,默认为1。默认的AGGREGATE是SUM,即结果集合中元素的score是所有集合对应元素进行SUM运算的值,而MIN和MAX是指,结果集合中元素的score是所有集合对应元素中最小值和最大值。
2、RedisTemplate 操作命令
(1)String(字符串)
redisTemplate.opsForValue();
(2)Hash(哈希)
redisTemplate.opsForHash();
(3)List(列表)
redisTemplate.opsForList();
(4)Set(集合)
redisTemplate.opsForSet();
(5)ZSet(有序集合)
redisTemplate.opsForZSet();
对于 Jedis
中操作大部分命令,RedisTemplate
有对应的封装方法,具体可以查看 RedisTemplate 。