初识Redis
认识NoSQL
-
SQL 关系型数据库 VS NoSQL 非关系型数据库
SQL关系型数据库 | NoSQL非关系型数据库 |
---|---|
结构化(Structured) | 非结构化(约束较少) |
关联的(Relational) | 非关联的 |
SQL查询 | 非SQL |
事务 ACID | 无事务 BASE |
磁盘 | 内存 |
垂直 | 水平 |
1.数据结构固定 2.相关业务对数据安全性、一致性要求较高 | 1.数据结构不固定 2.对一致性、安全性要求不高 3.对性能要求 |
认识Redis
特征:
键值(key-value)型 ,value支持多种不同数据结构,功能丰富
单线程,每个命令具备原子性
低延迟,速度快(基于内存,IO多路复用,良好的编码)
支持数据持久化
支持主从集群、分片集群
支持多语言客户端
5种常见数据结构
常见的5种数据类型,分别是:String、List、Set、Zset、Hash
String字符串
String是redis中最基本的数据类型,一个key对应一个value
String类型是二进制安全的,意思是redis的string可以包含任何数据。如数字,字符串,jpg图片或者序列化的对象
图例
下图是一个String类型的实例,其中键为hello,值为world
相关的命令使用
GET | 获取存储在给定键中的值 | GET name |
---|---|---|
SET | 设置储存在给定键中的值 | SET name value |
DEL | 删除存储在给定键中的值 | DEL name |
INCR | 将键存储的值加一 | INCR key |
DECR | 将键存储的值减一 | DECR key |
INCRBY | 将键存储的值加上整数 | INCRBY key amount |
DECRBY | 将键存储的值减去整数 | DECRBY key amout |
运用场景
缓存:经典使用场景,把常用信息,字符串,图片或者视频等信息放到redis中,redis作为缓存层,mysql作为持久化层,降低mysql的读写压力
计数器
redis是单线程模型,一个命令执行完才会执行下一个,同时数据可以一步落地到其他的数据源。
session
常见方案spring session +redis实现session共享
List 列表
Redis中的List其实就是链表(Redis用双端链表实现List)
使用List结构 ,我们可以轻松地实现最新消息排队功能(比如新浪微博的TimeLine)。List的另外一个应用就是消息队列,可以利用List的PUSH操作,将任务存放在List中,然后工作线程再用POP操作将任务取出进行执行。
图列
命令使用
RPUSH | 将给定值推入到列表右端 | RPUSH key value |
---|---|---|
LPUSH | 将给定值推入到列表左端 | LPUSH key value |
RPOP | 从列表的右端弹出一个值,并返回被弹出的值 | RPOP key |
LPOP | 从列表的左端弹出一个值,并返回被弹出的值 | LPOP key |
LRANGE | 获取列表在给定范围上的所有值 | LRANGE key 0 -1 |
LINDEX | 通过索引获取列表中的元素。你也可以使用负数下标,以-1表示列表的最后一个元素,-2表示列表的倒数第二个元素以此类推 | LINDEX key index |
使用列表的技巧
Ipush+Ipop=Stack(栈)
Ipush+rpop=Queue(队列)
Ipush+Itrim=Capped Collection(有限集合)
Ipush+brpop=Message Queue(消息队列)
运用场景
微博Timeline:有人发布微博,用Ipush加入时间轴,展示新的列表信息
消息队列
Set集合
Redis的Set是String类型的无序集合。集合成员是唯一的,这就意味着集合不能出现重复的数据。
Redis中集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)
图列
命令使用
SADD | 向集合添加一个或者多个成员 | SADD key value |
SCARD | 获取 集合的成员数 | SCARD key |
SMEMBERS | 返回集合中的所有成员 | SEMMBERS key value |
SIMEMBER | 判断 member元素是否是集合 key的成员 | SISMEMBER key member |
运用场景
标签 ,给用户添加标签,或者用户给消息添加 标签,这样有同一个标签 或者类型的标签的可以给推荐关注 的 事或者关注的人
点赞,或点踩,收藏等,可以放到set中实现
Hash散列
Redis hash 是一个string类型的field(字段)和value(值)的映射表,hash特别适合用于存储对象
图列
命令使用
HEST | 添加键值对 | HSET hash-key sub-key1 value 1 |
HGET | 获取指定散列键的值 | HGET hash-key key1 |
HGETALL | 获取散列中包含的所有键值对 | HGETALL hash-key |
HDEL | 如果给定键存在于散列中,那么就移除这个键 | HDEL hash-key sub-key1 |
运用场景
缓存:能直观,相比于string更节省空间,维护缓存信息,如用户信息,视频信息等
Zset有序集合
Redis 有序集合和集合一样也是string类型元素的集合,且不允许重复的成员。不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。
有序集合的成员是唯一的,但分数(score)却可以重复。有序集合是通过2种数据结构实现的:
压缩列表和跳跃表
图列
命令使用
ZADD | 将一个带有给定分值的成员添加到有序集合里面 | ZADD zset-key 178 member1 |
ZREM | 如果给定元素成员存在于有序集合中,那么就移除这个元素 | ZREM zset-key member 1 |
ZRANGE | 根据元素在有序集合中所处的位置,从有序集合中获取多个元素 | ZRANGE zset-key 0-1 withccores |
运用场景
排行榜:有序集合经典使用场景。例如小说视频等网站需要对用户上传的小说视频做排行榜,榜单可以按照用户关注数,更新时间,字数等打分。
3种特殊类型
HyperLogLogs(基数统计)
什么是基数
基数就是不重复的元素
HyperLogLogs基数统计用来解决什么问题?
这个结构可以非常省内存的去统计各种计数,比如注册IP数、每日访问IP数、页面实时UV、在线用户数,共同好友数等。
它的优势体现
一个大型的网站,每天IP比如有100万,粗算一个IP消耗15字节,那么100万个IP就是15M。而HyperLogLog在Redis中每个键占用的内容都是12K,理论存储近似接近2^64个值,不管存储的内容是什么,它一个基于基数估算的算法,只能比较准确的估算出基数,可以使用少量固定的内存去存储并识别集合中的唯一元素。而且这个估算的基数并不一定准确,是一个带有0.81%标准错误的近似值
Bitmap(位存储)
Bitmap即位图数据结构,都是操作二进制位来进行记录,只有0和1两个状态
解决什么问题
比如:统计用户信息,活跃或者不活跃,登录或者未登录,打卡或者不打卡。两个状态的,都可以使用Bitmaps!
相关命令使用
使用bitmap来记录 周一到周日的打卡!周一:1 周二:0 周三:0 周四:1……
geospatial(地理位置)
可以推算地理位置的信息:两地之间的距离,方圆几里的人
geoadd
添加地理位置
geopos
获取指定的成员的经度和纬度 获得当前定位,一定是一个坐标值!
geodist
如果不存在,返回空
georadius
附近的人 获得指定数量的人
数据结构:Steam
对消息队列的完善实现
设计
消息id的序列化生成
消息遍历
消息的阻塞和非阻塞读取
消息的分组消费
未完成消息的处理
消息队列监控
Stream详解
Stream的结构设计
生产和消费:
基本的增删改查
单一消费者的消费
消费组的消费
监控状态