Redis数据类型分析
数据库类型
关系型数据库 SQL
特点
1、基于表格的形式,以行存储数据,是一个二维的模式
2、存储的是结构化的数据,数据存储有固定的的模式,数据需要适应表结构
3、表与表之间有关联
4、大部分都支持sql(结构化查询语音),支持复杂的关联查询
5、支持事务ACID 实现数据一致性
限制
1、难以扩容
2、表结构修改困难
3、数据通常持久化到磁盘,高并发是磁盘的读写吃力
非关系型数据库 NoSQL
特点
1、存储非结构化的数据
2、表与表之间没关联,便于扩展
3、保证数据最终一致性
4、数据存储两大、高并发
5、支持分布式,数据分片存储,扩缩容简单
常见的非关系型数据库
KV 存储:Redis、Memcached
文档存储:MongoDB
列存储:Hbase
。。。
NewSQL
结合和SQL和NoSQL的特点
Redis
redis 特性
1、数据放在内存中,速度快
2、有丰富的数据结构
3、支持订阅发布,持久化,内存淘汰,事务,Lua脚本
4、集群、分布式
Memcached和redis的区别
Memcached只能存储KV,没有持久化机制,不支持主从复制,是多线程的
redis 安装
window
下载压缩包 Redis-x64-3.0.504.zip,解压
cmd启动:redis-server.exe redis.windows.conf
cmd客户端链接:redis-cli.exe -h 127.0.0.1 -p 6379 -a 123456(密码)
redis客户端链接
redis的使用
redis默认有16个库,key的最大长度是512M
常用的指令
flushdb 清空当前数据库
flushall 清空所有数据库
set tom 18 赋值
get tom 获取值
keys * 查看所有键
dbsize 获取键总数
exists tom 键是否存在
del tom nancy jay 删除键,支持多个键一起
rename tom tom1 重命名
type tom 查看类型
等等。。。。
redis的基本数据类型
String、List、Hash、Set、ZSet、Hyperloglog、Geo、Streams
String
存储类型
可以用来存储:int、float、String、
操作命令
getrange tom 0 1 获取指定范围
strlen tom 获取值长度
append tom good 字符串追加内容
mset tom 1 jack 2 批量设置,原子性
mget tom jack 批量获取
setnx tom sss 设置值,key存在,则不成功。
基于此实现分布式锁,del key 释放锁,释放锁失败,会导致其他节点获取不到锁,所以加个过期时间
set key value EX 10 NX 设置失效时间
incr tom 增值 ;默认是1
incrby tom 100
decr tom 递减
decrby tom 100 减100
set mf 2.6 浮点数增加
incrbyfloat mf 7.3
底层编码
redis 是基于k-v存储的,一般用hashtable实现最外层
每一个Key都对应一个dictEntry,通过指针指向key的存储结构和value的存储结构,next指向下一个键值对
set hello world 为例:
redis自己实现了一个字符串格式sds,hello指向一个SDS结构
value存储字符串时,redis没有直接用sds存储,而是存储在redisObject,redisObject最终指向实际的数据结构
SDS是什么
redis字符串的实现,本质上还是字符数组
为什么用SDS实现字符串
C语言没有字符串类型,只能用字符数组char[]实现;
使用字符数组容易溢出,遍历数组复杂度高,字符长度变更会做内存重分配
SDS特点
不担心内存溢出,还能扩容
取字符长度时复杂度为1
空间分配、惰性空间释放,减少内存重分配
String 有三种编码 int、embstr、raw
int 存储8个字节长整型
embstr 存储小于44字节的字符串
raw 大于44字节的字符串
编码的相互转化
int 数据不再是整数--->raw
int 大小超过long的范围----embstr
embstr 长度超过44 ---- raw
应用场景
缓存
分布式数据共享,如session
分布式锁 setnx 只有不存在是才添加成功,返回true
全局ID incrby tom 1000 利用原子性
计数器 int类型 incr 方法
限流
位操作
一个KV怎么存储一张表的数据
key 分层存储:
取值时一次性取,用list存储
缺点:key太长,占用空间
用hash来存储
Hash类型
存储类型
hash存储多个无序的键值对
Hash 的特点
1、把所有相关值聚集到一个key,节省空间
2、只用一个key,减少冲突
3、批量获取值,只用到一个命令,减小内存/IO/CPU消耗
Hash不适合的场景
1、field不能单独设超时时间
2、需要考虑分布式问题
操作命令
hset h1 f 6
hset h1 e 5
hmset h1 a 1 b 2 c 3
hget h1 a
hmget h1 a b c d
hkeys h1
hvals h1
hgetall h1
hdel h1 a
hdel h1
底层编码
是由两种数据结构实现的
zipList 压缩列表
hashtable 哈希表
ZipList
连续内存块组成的双向链表
何时使用ziplist
1、当哈希对象键值对数量<512
2、所有键值对的键和值的字符串长度都小于64字节
超过任意一个转换为hashtable
应用场景
1、String 能做的
2、存储对象类型的数据
3、购物车
key:userId;field:商品id;value:数量
hincr 加
hdecr 减
删除 hincrby key field -1
全选 hgetall
商品数:hlen
List 类型
存储类型
存储有序的字符串,元素可重复
操作命令
元素增减:
lpush queue a 左边添加
lpush queue b c
rpush queue d e 右边添加
lpop queue 左边删除
rpop queue 右边删除
lindex queue 0
lrange queue 0 -1
底层编码
quickList 存储了个双向链表,每个节点都是一个ziplist
总结:quickList就是一个数组+链表的结构
应用场景
列表
分布式环境的队列/栈,两个阻塞操作 BLPOP/BRPOP,可以设置超时时间
blpop key timeout 移除并获取列表的第一个元素,如果没有元素,会阻塞队列等到弹出元素或者超时为止
brpop类似
队列:先进先出 rpush blpop,左头右尾,右边进,左边出
栈:先进后出,rpush brpop
总结:Lisy存储有序的内容,用quickList实现,是数组+链表
Set 集合类型
存储类型
Set存储String类型的无序集合
操作命令
sadd myset a b c d --添加元素
smembers myset --获取所有元素
scard myset -- 统计元素个数
srandmember myset --随机获取一个元素
spop myset --随机弹出一个元素
srem myset d e f --移除元素
sismember myset a --查看a是否存在
底层编码
redis 用 intset或者hashtable 存储set,
如果元素都是整型的就用intset存储,如果不是整数类型或者元素大于512个就用hashtable(数组+链表)
应用场景
抽奖 spop myset
点赞、签到、打卡
t0001是微博Id,用like:t0001 表示这条微博的点赞信息
点赞这条微博 sadd like:t0001userId
取消点赞 srem like:t0001UserId
是否点赞 sismember like:t0001userId
点赞的所有用户 smembers like:t0001
点赞数 scard like:t0001
标签
用tags:1001 表是商品的标签
sadd tags:1001 标签1
sadd tags:1001 标签2
商品筛选
获取差集 sdiff set1 set2
获取交集 sinter set1 set2
获取并集 sunion set1 set2
sadd brand:huawei P40
sadd os:android P40
sadd screensize:6.0-6.2 P40
筛选商品,华为的、andriod、屏幕大小6.0-2.6
sinter brand:huawei os:andriod screensize:6.0-6.24
思考
相互关注
我关注的人也关注了他
可能认识的人
Zset有序集合
存储类型
sorted set 存储有序的元素,每个元素都有score,按照score从小到大排名,score相同,按asc码排序
操作命令
zadd myzset 10 java 20 php 30 ruby 40 cpp 50 python 添加元素
zrange myzset 0 -1 withscores 获取全部元素
zrevrange myzset 0 -1 withscores 获取全部元素
zrangebyscore myzset 20 30 根据区间获取元素
zrem myzset php cpp 移除元素,也可以按照score rank删除
zcard myzset 统计元素个数
zincrby myzset 5 python 分值递增
zcount myzset 20 60 根据分值统计个数
zrank myzset python 获取元素rank
zscore myzset python 获取元素score
底层编码
默认使用zipList,hash的小编码,quickList的Node,都是zipList
调表skipList
链表实现二分查找
应用场景
顺序会动态变化的列表
排行表,如百度热搜
zincrby hotNew:20210525 1 n6001 ----id为6001的新闻点击数加1
zrevrange hotNew:20210525 15 withscore 获取热搜前15
其他类型
BitMaps
Hyperloglogs
Geo
Stream
总结
数据结构总结
编码转换总结
应用场景总结
缓存---提升热点数据的访问速度
共享数据---数据的存储和共享的问题
全局ID----分布式全局Id的生成方案
分布式锁----进程间共享数据的原子操作
在线用户统计和计数
队列、栈---跨进程的队列/栈
消息队列----异步解耦的消息机制
服务注册与发现----RPC 通信机制的服务协调中心(Dubbo支持redis)
购物车
新浪微博用户消息时间线
抽奖逻辑
点赞签到打卡
商品标签
用户关注模型
电商产品筛选
排行榜