Redis的常用数据类型:String字符串,list列表,hash哈希,set集合,zset有序集合;
一,String
单个value最大存储512MB。
使用场景
存储验证码等普通 key/value
session共享
计数器
利用redis单线程,线程安全 实现:value为数字类型,命令:incr key
redisTemplate.opsForValue().increment(Object key);
实现分布式锁
原理:
setnx key value (set if not exist)
只要key不存在,就保存key value;若存在,不做操作。一个线程先拿到锁(setnx 保存key到value),其它线程再setnx key, 返回false。对应代码:redisTemplate.opsForValue().setIfAbsent(key, value) 保存成功返回true 失败返回false。注意:用完要释放锁。
存在问题:
- 线程拿到锁,业务逻辑抛异常,不能释放锁。
解决:把业务代码放进try catch finally。在finally释放锁。 - 线程拿到锁,突然服务挂了或网络问题,finally也不能执行,不能释放锁。
解决:设置key过期时间,set key时就传入过期时间。 - 高并发下,线程A进去业务逻辑 -> 线程A执行时间超过设置的过期时间 -> 这时释放了锁,线程B拿到锁,执行业务代码 -> 线程A此时执行完了,释放了B的锁,,以此循环。
解决:线程A的key只能线程A删除。给每个线程一个UUID,作为value存入redis,删除key前先校验value。
Redisson
工具更轻松帮我们解决以上的问题。
二,Hash
每个 hash 可以存储 2^32 - 1 键值对(40多亿)。
优点:
适合存储对象数据;
同类数据归类整合存储;
相比string,消耗内存和CPU更小;
相比string存储更节省空间;
缺点:
过期功能不能用在field上,只能用在key上;
redis集群架构下不适合大规模使用;
使用场景
电商购物车
应用:以 userId 为 key,goodsId 为 field,商品数量为 value。
操作:
# 添加商品
hset cart:xiaohua 10001 2
# 增加数量
hincrby cart:xiaohua 10001
# 商品数量
hlen cart:xiaohua 10001
存储商品详情
三,List
Redis列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)一个列表最多可以包含 2^32 - 1 个元素 (4294967295, 每个列表超过40亿个元素)。
使用场景:
消息队列
订阅的多个公众号推送的消息
redisTemplate.opsForList().leftPush("Message:", ObjectA);
redisTemplate.opsForList().leftPush("Message:", ObjectB);
List<Object> boList = (List<Object>)redisTemplate.opsForList().range("Message:", 0, -1);
取最新N个数据的操作
存放文章最新评论
四,Set
Redis的 Set 是 String 类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据。
Redis 中集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)
。
集合中最大的成员数为 2^32 - 1 (4294967295, 每个集合可存储40多亿个成员)。
使用场景
利用set的集合操作
关注模型
(共同关注,我关注的人同时也关注他)
SADD key member1 [member2] :向集合添加一个或多个成员
SINTER key1 [key2] :返回给定所有集合的交集(筛选共同关注的人)
SDIFF key1 [key2] :返回给定所有集合的差集(返回key1中key2不存在的值)
SISMEMBER key member :判断 member 元素是否是集合 key 的成员
SMEMBERS key :返回集合中的所有成员
朋友圈点赞、收藏,标签
点赞:sadd like:{消息id/文章id} {用户id}
取消点赞:srem like:{消息id/文章id} {用户id} //移除集合中的元素
检查是否点过赞:sismember like:{消息id/文章id} {用户id}
获取点赞的用户列表:smembers like:{消息id/文章id}
获取点赞用户数:scard like:
微信抽奖
加入抽奖集合:sadd key {userId}
查看参与抽奖的所有用户:smembers key
抽取count名中奖者:srandmember key [count] //返回集合中一个或多个随机数
spop key [count] //移除并返回集合中的一个随机元素
五,ZSet
Redis 有序集合和集合一样也是string类型元素的集合,且不允许重复的成员。不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。有序集合的成员是唯一的,但分数(score)却可以重复。
集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)
。 集合中最大的成员数为 2^32 - 1 (4294967295, 每个集合可存储40多亿个成员)。
使用场景
分数排序、排行榜
redisTemplate.opsForZSet().incrementScore("designer:hot", 文章id, 1);
LinkedHashSet set = (LinkedHashSet<Long>)
//取前50条热门数据
redisTemplate.opsForZSet().reverseRange("paper:hot", 0, 49);
评论区