本文总结:Redis是一款基于内存的键值型NoSQL数据库,具有高性能、持久化和集群支持等特性。它提供五种基本数据结构:String(字符串)、Hash(哈希)、List(列表)、Set(集合)和ZSet(有序集合),以及BitMap、HyperLogLog、GEO和Stream四种扩展结构。String适合存储简单数据,Hash适合存储对象字段,List实现队列功能,Set用于去重,ZSet支持排序。扩展结构中,BitMap适用于状态标记,HyperLogLog用于基数统计,GEO处理地理位置,Stream实现消息队列。Redis支持多种业务场景,如缓存、排行榜、社交关系等,通过丰富的数据类型和命令满足不同需求。
Redis:将数据存储于内存的键值型NoSQL数据库。
Redis特征
1、键值型
2、单线程,每个命令具备原子性,虽然Redis6.0后有多线程,但是只是对于网络请求,核心命令还是单线程
3、低延迟,速度快(因为它是基于内存、IO多路复用、多种数据结构良好的编码、RESP协议)
4、支持数据持久化
5、支持主从集群、分片集群
6、支持多语言客户端
key一般都是string类型的,value可以是各种类型的,相关类型的命令不常用的不用背,具体只要会用,可以去查官方文档。
redis的五大基本类型
通用的命令:KEYS,DEL,EXISTS,EXPIRE,TTL
String类型:根据字符串格式的不同又分为string,int,float,不管是哪种格式底层都是字节数组形式存储,只是编码方式不同。
String常用命令:SET,GET,MSET,MGET,INCR,INCRBY,INCRBYFLOAT,SETNX,SETEX。
Redis的key允许有多个单词形成层级结构,多个单词之间用“:”隔开,格式例如,项目名:业务名:类型:id。如果value是一个java对象例如User对象,可以将对象序列化成json字符串来存储。
因为String类型是用json存储,要对里面的某个value进行修改非常地不方便,可以用Hash。
Hash类型:value是无序字典,类似java中的HashMap结构。Hash结构可以将对象的每个字段独立存储,相比于String多了个field字段名,使其可以针对某个字段做CRUD。
Hash常用命令:HSET,HGET,HMSET,HMGET,HGETALL,HKEYS,HVALS,HINCRBY,HSETNX。
List类型:与java中的LinkedList类似,可以看作是一个双向链表的结构,既可以支持正向检索也可以支持反向检索。特征也与LinkedList类似,有序、元素可以重复、插入和删除快、查询速度一般,像点赞场景等。
List常用命令:LPUSH,LPOP,RPUSH,RPOP,LRANGE,BLPOP和BRPOP。
Set类型:与java中的HashSet类似,可以看作是一个value为null的HashMap。特征也与HashSet类似,无序、元素不可重复、查找快、支持交集并集差集等功能,像共同好友场景等。
Set常用命令:
在单个集合中的操作SADD,SREM,SCARD,SISMEMBER,SMEMBERS
在多个集合中的操作SINTER,SDIFF,SUNION
ZSet类型:与java中的TreeSet类似,都是一个可排序的set集合,但底层的数据结构差别却很大。ZSet(SortedSet)中的每一个元素都带有一个score属性,可以基于score属性对元素排序,底层的实现是一个跳表SkipList加hash表。SortedSet的特性是,可排序、元素不重复、查询速度快,像排行榜场景等。
ZSet常用命令:ZADD,ZREM,ZSCORE,ZRANK,ZCARD,ZCOUNT,ZINCRBY,ZRANGE,ZRANGEBYSCORE,ZINTER,ZDIFF,ZUNION。
注:这里都是默认按升序排序,要降序则在命令的Z后面加上REV。
随着Redis的版本更新还支持以下四种结构:BitMap、HyperLogLog、GEO(Geospatial)、Stream
BitMap
它是一种使用位(bit)来表示数据的紧凑数据结构,每个位可以存两个值0和1,用于表示某种状态或标志,在大规模存储二值数据非常高效且节约空间(如布尔值),最经典的就是签到记录场景,那我们可以用0表示未签到,1表示签到,每个用户对应一个键,bitmap的每一位表示用户在某一天是否打卡签到,如0101表示用户第1天和第3天签到、1010表示用户第2天和第4天签到了。
一般最传统的表示状态方法就是使用itn status=0和int status=1表示两种状态,但是int是4字节嘛,相当于32位,那它的占用空间肯定是远远大于bitmap的1位的,所以选用bitmap最合适。学会bitmap实现签到,那类似的会员啊什么的两种状态的也都是类似。
要实现bitmap,JDK自带了BitSet类,还有Redis也支持bitmap高级数据结构,那考虑到项目的分布式、可扩展性,这里可以采用Redis的bitmap来实现SETBIT user:signins :{年份}:{用户id} {第几天} 1来存储和GETBIT user:signins :{年份}:{用户id} {第几天}来查看是0还是1
HyperLogLog
HyperLogLog是一种用于基数估计的数据结构,它可以在使用很少内存的情况下(每个键只需12KB)估算一个集合中不重复元素的数量。但是,请注意,HyperLogLog提供的是近似值。
常见命令:
PFADD:将元素添加到HyperLogLog中
PFCOUNT:返回HyperLogLog中基数的估计值
PFMERGE:将多个HyperLogLog合并为一个
应用场景:
统计网站的独立访客数(UV)
统计搜索关键词的不同数量
任何需要去重计数且可以接受近似结果的场景
GEO
Geospatial是Redis中用于处理地理位置的数据结构。它使用有序集合(Sorted Set)存储位置信息,并提供了计算距离、查找附近位置等功能。
常见命令:
GEOADD:添加地理位置(经度、纬度、名称)
GEODIST:计算两个位置之间的距离
GEORADIUS:查找指定半径内的位置
GEOHASH:返回位置的Geohash表示
应用场景:
附近的人或地点
计算两个地点之间的距离
地理位置相关的推荐系统
Stream
Stream是Redis 5.0引入的一种新的数据结构,它是一个可持久化的消息队列,解决了List类型的两个问题:1、生产者需要自主实现全局唯一ID ,2、不能以消费组形式消费问题。Stream中的每个条目都有一个唯一的ID,并且可以包含多个键值对。Stream支持消费者组,允许多个消费者协同处理消息。
常见命令:
XADD:向Stream中添加消息
XREAD:读取Stream中的消息
XGROUP:创建、管理消费者组
XREADGROUP:通过消费者组读取消息
应用场景:
消息队列:替代传统的Pub/Sub,因为Stream可以持久化消息
事件溯源:记录事件的发生顺序
日志收集:将多个来源的日志汇总到一个Stream中