写点什么

Redis 不只是 get set,八种数据类型及应用场景分析,java 技术栈面试题

用户头像
极客good
关注
发布于: 刚刚

1、为什么要把数据放在内存中?


  1. 内存的速度更快,10W QPS

  2. 减少计算的时间,减轻数据库压力


2、如果是用内存的数据结构作为缓存,为什么不用 HashMap 或者 Memcached?


  1. 更丰富的数据类型

  2. 支持多种编程语言

  3. 功能丰富:持久化机制、内存淘汰策略、事务、发布订阅、pipeline、LUA

  4. 支持集群、分布式


3、Memcached 和 redis 的区别是什么?


Memcached 只能存储 KV、没有持久化机制、不支持主从复制、是多线程的。


Reids 默认有 16 个库(0-15),可以在配置文件 redis.conf 中修改。


databases 16


Redis Key 的最大长度限制是 512M,值得限制不同,有的是用长度限制的,有的是用个数限制的。


[](


)String


=================================================================


[](


)介绍


=============================================================


最基本也是最常用的数据类型就是 String。get 和 set 命令就是 String 的操作命令,Redis 的字符串被叫做二进制安全的字符串(Binary-safe strings)。


String 可以存储三种类型,INT(整数)、float(单精度浮点数)、string(字符串)。


[](


)操作命令


===============================================================


下面是它的一些操作命令

存值(如果对同一个 key set 多次会直接覆盖旧值)

set jack 2673

取值

get jack

查看所有键

keys *

获取键总数(生产环境数据量大,慎用)

dbsize

查看键是否存在

exists jack

删除键

del jack tonny

重命名键

rename jack tonny

查看类型

type jack

获取指定范围的字符

getrange jack 0 1

获取值长度

strlen jack

字符串追加内容

append jack good

设置多个值(批量操作,原子性)

mset jack 2673 tonny 2674

获取多个值

mget jack tonny

设置值,如果 key 存在,则不成功

setnx jack shuaige

基于此实现分布式锁

set key value [expiration EX seconds|PX milliseconds][NX|XX]

(整数)值递增(值不存在会得到 1)

incr jack


incrby jack 100

(整数)值递减

decr jack


decrby jack 100

浮点数增量

set mf 2.6


incrbyfloat mf 7.3


[](


)应用场景


===============================================================


1、缓存


String 类型,这是最常用的,可以缓存一些热点数据,比如首页新闻,可以显著提升热点数据的访问速度,同时减轻 DB 压力。


2、分布式数据共享


String 类型,因为 Redis 是分布式的独立服务,可以在多个应用之间共享。


例如:分布式 Session


<dependency>


<groupId>org.springframework.session</groupId>


<artifactId>spring-session-data-redis</artifactId>


</dependency>


3、分布式锁


参考《介绍几种常见的分布式锁写法》


4、全局 ID


INT 类型,INCRBY,利用原子性


incrby userid 1000


(分表分库的场景,一次性拿一段)


5、计数器


INT 类型,INCR 方法


例如:文章的阅读量,微博点赞数,允许一定的延迟,先写入 Redis 再定时同步到数据库


6、限流


INT 类型,INCR 方法


以访问者的 IP 和其他信息作为 key,访问一次增加一次计数,超过次数则返回 false。


[](


)Hash


===============================================================


[](


)介绍


=============================================================


现在有一张 teacher 表



假设我们还是通过 String 类型存储的话,存储的时候就要把 Teacher 实体类进行序列化,然后作为 value 只存储进去;修改的时候,也需要把 value 先取出来进行反序列化,比如把年龄更改为 21 岁,然后再序列化,再存进去,十分的繁琐,增加开销。


我们需要单独获取、修改一个值,这时我们可以通过 key 分层的方式来实现,如下表:


![Redis 不只是 get set,八种数据类型及应用场景分析](https://img-blog.cs


【一线大厂Java面试题解析+核心总结学习笔记+最新架构讲解视频+实战项目源码讲义】
浏览器打开:qq.cn.hn/FTf 免费领取
复制代码


dnimg.cn/img_convert/43495c2dcdb4df34de9c1fdd5e74fe18.png)


但是这样 key 会很多,key 也很长,占用空间,有没有更好的办法,这时候就用到我们的 Hash 类型,如下两张表所示:




这样也便于集中管理,划分的粒度不同,可以按照实际场景,key 的过期时间,灵活度考虑选取哪一种存储方式。


Hash 用来存储多个无序的键值对,最大存储数量 2^32-1(40 亿左右)。


优点:


  1. 把所有相关的值聚集到一个 Key 中,节省内存空间

  2. 只使用一个 Key,减少 Key 冲突

  3. 当需要批量获取值的时候,只需要使用一个命令,减少内存/IO/CPU 的消耗


缺点:


  1. Field 不能单独设置过期时间

  2. 需要考虑数据量分布的问题(field 非常多的时候,无法分布到多个节点)


[](


)操作命令


===============================================================

设置、批量设置值

hset h1 f 6


hset h1 e 5


hmset h1 a 1 b 2 c 3 d 4

取值

hget h1 a

批量取值

hmget h1 a b c d

获取所有 field

hkeys h1

获取所有 field 的值

hvals h1

返回哈希表中,所有的字段和值

hgetall h1

删除 field

hdel h1 a

获取哈希表中字段的数量

hlen h1


[](


)应用场景


===============================================================


String 可以做的事情,Hash 都可以做。再补充一个场景,购物车:



key:用户 id;field:商品 id;value:商品数量;


+1:hincr;


-1:hdecr;


删除:hincrby key field -1;


全选:hgetall;


商品数:hlen;


[](


)List


===============================================================


[](


)介绍


=============================================================


存储有序的字符串(从左到右),元素可以重复,最大存储数量 2^32-1(40 亿左右)。


下面通过画图来演示一下入队列,出队列



[](


)操作命令


===============================================================

左推

lpush queue a


lpush queue b c

右推

rpush queue d e

左边移除并返回列表的第一个元素

lpop queue

右边移除并返回列表的第一个元素

rpop queue

通过索引获取列表中的元素

lindex queue 0

返回列表中指定区间内的元素

lrange queue 0 -1


[](


)应用场景


===============================================================


1、列表


例如用户的消息列表、网站的公告列表、活动列表、博客的文章列表、评论列表等,通过 LRANGE 取出一页,按顺序显示。



2、队列/栈


List 还可以当做分布式环境的队列/栈使用。


队列:先进先出,rpush 和 blpop


栈:先进后出,rpush 和 brpop


这里介绍两个阻塞的弹出操作:blpop/brpop,可以设置超时时间(单位:秒)。


blpop:blpop key1 timeout,移出并获取列表的第一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。


brpop:brpop key1 timeout,移出并获取列表的最后一个元素,如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。


[](


)Set


==============================================================


[](


)介绍


=============================================================


Set 存储 String 类型的无序集合,最大存储数量 2^32-1(40 亿左右)。


如下图所示:



[](


)操作命令


===============================================================

添加一个或多个元素

sadd myset a b c d e f g

获取所有元素

smembers myset

统计元素个数

scard myset

随机获取一个元素

srandmember myset

随机弹出一个元素

spop myset

移除一个或者多个元素

srem myset d e f

查看元素是否存在

sismember myset a

获取差集

sdiff set1 set2

获取交集

sinter set1 set2

获取并集

sunion set1 set2


[](


)应用场景


===============================================================


1、抽奖


随机获取元素:spop myset


2、点赞、签到、打卡



我们以微博举例子,假设这条微博的 ID 是 t1001,用户 ID 是 u6001,


用 dianzan:t1001 来维护 t1001 这条微博的所有点赞用户。


点赞了这条微博:sadd dianzan:t1001 u6001


取消点赞:srem dianzan:t1001 u6001


是否点赞:sismember dianzan:t1001 u6001


点赞的所有用户:smembers dianzan:t1001


点赞数:scard dianzan:t1001


比关系型数据库简单了许多。

用户头像

极客good

关注

还未添加个人签名 2021.03.18 加入

还未添加个人简介

评论

发布
暂无评论
Redis不只是get set,八种数据类型及应用场景分析,java技术栈面试题