一些小问题

Redis一共有几种数据类型?(注意是数据类型不是数据结构)

一共是八种,String、Hash、Set、List、Zset、Hyperloglog、Geo、Streams。

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

内存的速度更快,10W QPS

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

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

更丰富的数据类型

支持多种编程语言

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

支持集群、分布式

Memcached和redis的区别是什么?

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

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

关于其他有趣的 Reids 的内容可以移步这儿:https://www.cnblogs.com/zwtblog/tag/Redis/

String

get和set命令就是String的操作命令,Redis的字符串被叫做二进制安全的字符串(Binary-safe strings)。

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

操作命令

  1. # 存值(如果对同一个key set多次会直接覆盖旧值)
  2. set jack 2673
  3. # 取值
  4. get jack
  5. # 查看所有键
  6. keys *
  7. # 获取键总数(生产环境数据量大,慎用)
  8. dbsize
  9. # 查看键是否存在
  10. exists jack
  11. # 删除键
  12. del jack tonny
  13. # 重命名键
  14. rename jack tonny
  15. # 查看类型
  16. type jack
  17. # 获取指定范围的字符
  18. getrange jack 0 1
  19. # 获取值长度
  20. strlen jack
  21. # 字符串追加内容
  22. append jack good
  23. # 设置多个值(批量操作,原子性)
  24. mset jack 2673 tonny 2674
  25. # 获取多个值
  26. mget jack tonny
  27. # 设置值,如果key存在,则不成功
  28. setnx jack shuaige
  29. # 基于此实现分布式锁
  30. set key value [expiration EX seconds|PX milliseconds][NX|XX]
  31. # (整数)值递增(值不存在会得到1)
  32. incr jack
  33. incrby jack 100
  34. # (整数)值递减
  35. decr jack
  36. decrby jack 100
  37. # 浮点数增量
  38. set mf 2.6
  39. incrbyfloat mf 7.3

应用场景

1、缓存

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

2、分布式数据共享

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

例如:分布式Session

  1. <dependency>
  2. <groupId>org.springframework.session</groupId>
  3. <artifactId>spring-session-data-redis</artifactId>
  4. </dependency>

3、分布式锁

详情见博客:https://www.cnblogs.com/zwtblog/p/15185894.html

4、全局ID

INT类型,INCRBY,利用原子性

  1. incrby userid 1000(分表分库的场景,一次性拿一段)

5、计数器

INT类型,INCR方法

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

6、限流

INT类型,INCR方法

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

Hash

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

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

优点:

  1. 把所有相关的值聚集到一个Key中,节省内存空间
  2. 只使用一个Key,减少Key冲突
  3. 当需要批量获取值的时候,只需要使用一个命令,减少内存/IO/CPU的消耗

缺点:

  1. Field不能单独设置过期时间
  2. 需要考虑数据量分布的问题(field非常多的时候,无法分布到多个节点)

操作命令

  1. # 设置、批量设置值
  2. hset h1 f 6
  3. hset h1 e 5
  4. hmset h1 a 1 b 2 c 3 d 4
  5. # 取值
  6. hget h1 a
  7. # 批量取值
  8. hmget h1 a b c d
  9. # 获取所有field
  10. hkeys h1
  11. # 获取所有field的值
  12. hvals h1
  13. # 返回哈希表中,所有的字段和值
  14. hgetall h1
  15. # 删除field
  16. hdel h1 a
  17. # 获取哈希表中字段的数量
  18. hlen h1

应用场景

String可以做的事情,Hash都可以做。

再补充一个场景,购物车

List

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

操作命令

  1. # 左推
  2. lpush queue a
  3. lpush queue b c
  4. # 右推
  5. rpush queue d e
  6. # 左边移除并返回列表的第一个元素
  7. lpop queue
  8. # 右边移除并返回列表的第一个元素
  9. rpop queue
  10. # 通过索引获取列表中的元素
  11. lindex queue 0
  12. # 返回列表中指定区间内的元素
  13. lrange queue 0 -1

应用场景

1、列表

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

2、队列/栈

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

队列:先进先出,rpush 和 blpop

栈:先进后出,rpush 和 brpop

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

  1. blpopblpop key1 timeout
  2. 移出并获取列表的第一个元素,
  3. 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。
  4. brpopbrpop key1 timeout
  5. 移出并获取列表的最后一个元素,
  6. 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。

Set

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

操作命令

  1. # 添加一个或多个元素
  2. sadd myset a b c d e f g
  3. # 获取所有元素
  4. smembers myset
  5. # 统计元素个数
  6. scard myset
  7. # 随机获取一个元素
  8. srandmember myset
  9. # 随机弹出一个元素
  10. spop myset
  11. # 移除一个或者多个元素
  12. srem myset d e f
  13. # 查看元素是否存在
  14. sismember myset a
  15. # 获取差集
  16. sdiff set1 set2
  17. # 获取交集
  18. sinter set1 set2
  19. # 获取并集
  20. sunion set1 set2

应用场景

1、抽奖

随机获取元素:spop myset

2、点赞、签到、打卡

  1. 我们以微博举例子,假设这条微博的IDt1001,用户IDu6001
  2. dianzan:t1001 来维护 t1001 这条微博的所有点赞用户。
  3. 点赞了这条微博:sadd dianzan:t1001 u6001
  4. 取消点赞:srem dianzan:t1001 u6001
  5. 是否点赞:sismember dianzan:t1001 u6001
  6. 点赞的所有用户:smembers dianzan:t1001
  7. 点赞数:scard dianzan:t1001
  8. 比关系型数据库简单了许多。

3、商品标签

用 tags : i8001 来维护商品所有的标签。

  1. sadd tags:i8001 画面清晰细腻
  2. sadd tags:i8001 真彩清晰显示屏
  3. sadd tags:i8001 流畅至极

4、商品筛选

华为P50上线了,支持民族品牌,加到各个标签中去。

  1. sadd brand:huawei p50
  2. sadd os:android p50
  3. sadd screensize:6.0-6.24 p50

买的时候筛选,牌子是华为,操作系统是安卓,屏幕大小在6.0-6.24之间的,取交集:

sinter brand:huawei os:android screensize:6.0-6.24

ZSet

sorted set 存储有序的元素。每个元素都有个 score,按照 score 从小到大排序。

score 相同时,按照 key 的ASCII码排序。

操作命令

  1. # 添加元素
  2. zadd myzset 10 java 20 php 30 ruby 40 cpp 50 python
  3. # 获取全部元素
  4. zrange myset 0 -1 withscores
  5. zrevrange myzset 0 -1 withscores
  6. # 根据分数区间获取元素
  7. zrangebyscore myzset 20 30
  8. # 移除元素(也可以根据score rank删除)
  9. zrem myzset php cpp
  10. # 统计元素个数
  11. zcard myzset
  12. # 分值增加
  13. zincrby myzset 5 python
  14. # 根据分值min和max统计个数
  15. zcount myzset 20 60
  16. # 获取python排名
  17. zrank myzset python
  18. # 获取元素分数
  19. zscore myzset python

应用场景

1、排行榜

今天是2021年5月23号,建一个 key 为 hotSearch:20210523 的 zset。

这条新闻的id是n1234,每点击一下:zincrby hotSearch:20210523 1 n1234

获取热搜排行榜前十条:zrevrange hotSearch:20210523 0 10 withscores

BitMaps

BitMaps是在字符串类型上定义的位操作,一个字节由8个二进制位组成。

操作命令

  1. # 设置字符串key为k1,value为mic
  2. set k1 mic
  3. # 取k1的第七位,结果是0
  4. getbit k1 6
  5. # 取k1的第八位为0,此时的ASCII码是108,对应字母是l
  6. setbit k1 7 0
  7. # 所以取出来值为lic
  8. get k1
  9. # 统计二进制中1的个数,一共是12个
  10. bitcount k1
  11. # 获取第一个1或者0的位置
  12. bitpos k1 1
  13. bitpos k1 1
  1. BITOP AND destkey key [key ...],对一个或多个key求逻辑并,并将结果保存到 destkey
  2. BITOP OR destkey key [key ...],对一个或多个key求逻辑或,并将结果保存到 destkey
  3. BITOP XOR destkey key [key ...],对一个或多个key求逻辑异或,并将结果保存到 destkey
  4. BITOP NOT destkey key,对给定key求逻辑非,并将结果保存到 destkey

应用场景

1、连续在线用户

  1. setbit firstday 0 1 //设置第一天uid是0的用户登录
  2. setbit firstday 1 0 //设置第一天uid是1的用户未登录
  3. setbit firstday 2 1 //设置第一天uid是2的用户登录
  4. ...
  5. setbit secondday 0 0 //设置第二天uid是0的用户未登录
  6. setbit secondday 1 1 //设置第二天uid是1的用户登录
  7. setbit secondday 2 1 //设置第二天uid是2的用户登录
  8. ... //以此类推
  9. 那么在算连续七天在线用户就是:
  10. BITOP AND 7_both_online_users firstday secondday thirdday fourthday fifthday sixthday seventhday

2、应用访问统计

3、在线用户统计

Hyperloglog

Hyperloglog 提供了一种不太精确的基数统计方法,用来统计一个集合中不重复的元素个数,

在 Redis 中实现的 Hyperloglog,只需要12k内存就能统计2^64个数据。

  1. public static void main(String[] args) {
  2. Jedis jedis = new Jedis("39.103.144.86", 6379);
  3. float size = 100000;
  4. for (int i = 0; i < size; i++) {
  5. jedis.pfadd("hll", "hll-" + i);
  6. }
  7. long total = jedis.pfcount("hll");
  8. System.out.println(String.format("统计个数: %s", total));
  9. System.out.println(String.format("正确率: %s", (total / size)));
  10. System.out.println(String.format("误差率: %s", 1 - (total / size)));
  11. jedis.close();
  12. }

操作命令

  1. PFADD key element [element ...]
  2. 添加指定元素到 HyperLogLog 中。
  3. PFCOUNT key [key ...]
  4. 返回给定 HyperLogLog 的基数估算值。
  5. PFMERGE destkey sourcekey [sourcekey ...]
  6. 将多个 HyperLogLog 合并为一个 HyperLogLog

应用场景

1、统计网站的UV,或者应用的日活、月活,存在一定的误差。

Geo

操作命令

  1. # 存经纬度
  2. geoadd location 121.445 31.213 shanghai
  3. # 取经纬度
  4. geopos location shanghai

应用场景

1、增加地址位置信息、获取地址位置信息

2、计算两个位置的距离

3、获取指定范围内的地理位置集合

  1. public static void main(String[] args) {
  2. Jedis jedis = new Jedis("39.103.144.86", 6379);
  3. Map<String, GeoCoordinate> geoMap = new HashMap<>();
  4. GeoCoordinate coordinate = new GeoCoordinate(121.445, 31.213);
  5. geoMap.put("shanghai", coordinate);
  6. jedis.geoadd("positions", geoMap);
  7. System.out.println(jedis.geopos("positions", "shanghai"));
  8. jedis.close();
  9. }

Streams

Redis Stream 是 Redis 5.0 版本新增加的数据结构。

Redis Stream 主要用于消息队列(MQ,Message Queue),Redis 本身是有一个 Redis 发布订阅 (pub/sub) 来实现消息队列的功能,但它有个缺点就是消息无法持久化,如果出现网络断开、Redis 宕机等,消息就会被丢弃。

简单来说发布订阅 (pub/sub) 可以分发消息,但无法记录历史消息。

Redis Stream 提供了消息的持久化和主备复制功能,可以让任何客户端访问任何时刻的数据,并且能记住每一个客户端的访问位置,还能保证消息不丢失。

Redis Stream 的结构如下所示,它有一个消息链表,将所有加入的消息都串起来,每个消息都有一个唯一的 ID 和对应的内容:

每个 Stream 都有唯一的名称,它就是 Redis 的 key,在我们首次使用 xadd 指令追加消息时自动创建。

上图解析:

  • Consumer Group :消费组,使用 XGROUP CREATE 命令创建,一个消费组有多个消费者(Consumer)。
  • last_delivered_id :游标,每个消费组会有个游标 last_delivered_id,任意一个消费者读取了消息都会使游标 last_delivered_id 往前移动。
  • pending_ids :消费者(Consumer)的状态变量,作用是维护消费者的未确认的 id。 pending_ids 记录了当前已经被客户端读取的消息,但是还没有 ack (Acknowledge character:确认字符)。

操作命令

  1. 消息队列相关命令:
  2. XADD - 添加消息到末尾
  3. XTRIM - 对流进行修剪,限制长度
  4. XDEL - 删除消息
  5. XLEN - 获取流包含的元素数量,即消息长度
  6. XRANGE - 获取消息列表,会自动过滤已经删除的消息
  7. XREVRANGE - 反向获取消息列表,ID 从大到小
  8. XREAD - 以阻塞或非阻塞方式获取消息列表
  9. 消费者组相关命令:
  10. XGROUP CREATE - 创建消费者组
  11. XREADGROUP GROUP - 读取消费者组中的消息
  12. XACK - 将消息标记为"已处理"
  13. XGROUP SETID - 为消费者组设置新的最后递送消息ID
  14. XGROUP DELCONSUMER - 删除消费者
  15. XGROUP DESTROY - 删除消费者组
  16. XPENDING - 显示待处理消息的相关信息
  17. XCLAIM - 转移消息的归属权
  18. XINFO - 查看流和消费者组的相关信息;
  19. XINFO GROUPS - 打印消费者组的信息;
  20. XINFO STREAM - 打印流信息

应用场景

应用场景小结

缓存======提升热点数据的访问速度

共享数据======数据的存储和共享的问题

全局ID======分布式全局ID的生成方案(分库分表)

分布式锁======进程间共享数据的原子操作保证

在线用户统计和计数

队列、栈======跨进程的队列/栈

消息队列======异步解耦的消息机制

服务注册与发现======RPC通信机制的服务协调中心(Dubbo支持Redis)

购物车

新浪用户消息时间线

抽奖逻辑(礼物、转发)

点赞、签到、打卡

商品标签

用户(商品)关注(推荐)模型

电商产品筛选

排行榜

Redis-数据类型-应用场景的更多相关文章

  1. Redis数据类型使用场景及有序集合SortedSet底层实现详解

    Redis常用数据类型有字符串String.字典dict.列表List.集合Set.有序集合SortedSet,本文将简单介绍各数据类型及其使用场景,并重点剖析有序集合SortedSet的实现. Li ...

  2. Redis数据类型应用场景及具体方法总结

    StringsStrings 数据结构是简单的key-value类型,value其实不仅是String,也可以是数字.使用Strings类型,你可以完全实现目前 Memcached 的功能,并且效率更 ...

  3. redis数据类型及使用场景

    Redis数据类型  String: Strings 数据结构是简单的key-value类型,value其实不仅是String,也可以是数字. 常用命令:  set,get,decr,incr,mge ...

  4. redis 数据类型详解 以及 redis适用场景场合

    1.  MySql+Memcached架构的问题 实际MySQL是适合进行海量数据存储的,通过Memcached将热点数据加载到cache,加速访问,很多公司都曾经使用过这样的架构,但随着业务数据量的 ...

  5. redis的使用场景和基本数据类型

    一:redis使用的场景 redis是一个高性能的NoSQL数据库,特点是高性能,持久存储,适应高并发的应用场景. 下面看看它的使用场景1.取最新N个数据的操作比如取网站的最新文章,通过下面方式,我们 ...

  6. redis 数据类型详解 以及 redis适用场景场合(滴滴)

    滴滴的面试官问了个问题关于redis的: 我现在想服务器每分钟接收一个用户的请求小于60个,如何处理: 答:使用Redis 缓存服务器,可以设置key=用户ID value不停地加一到了60就停止,然 ...

  7. Redis五种数据类型应用场景

    目录 1.1 回顾 2.1 应用场景 2.1.1 String 2.1.2 Hash 2.1.3 List 2.1.4 Zet 2.1.5 zset 3.1 小结 1.1 回顾 Redis的五种数据类 ...

  8. redis数据类型及应用场景

    0.key的通用操作 KEYS * keys a keys a* 查看已存在所有键的名字 ****TYPE 返回键所存储值的类型 ****EXPIRE\ PEXPIRE 以秒\毫秒设定生存时间 *** ...

  9. Redis全方位详解--数据类型使用场景和redis分布式锁的正确姿势

    一.Redis数据类型 1.string string是Redis的最基本数据类型,一个key对应一个value,每个value最大可存储512M.string一半用来存图片或者序列化的数据. 2.h ...

  10. Redis的使用场景 by 杨卫华

    转载自新浪微博架构师杨卫华的博客 http://timyang.net/tag/redis/,省略了部分内容 按:杨卫华在2010年就已经测试了Redis的性能,并给出了初步的结论:“Redis性能惊 ...

随机推荐

  1. squid异常停止的排查步骤

    今天重启squid的时候发现,squid启动后,status 一会就stop了 whoami@blackman:~/script/AutoProxy-master/main/server$ sudo ...

  2. jmeter正则表达式介绍

    分三个层次介绍: 1. jmeter正则表达式有什么作用? 2. 正则表达式在哪? 3. 正则表达式怎么用? 1. jmeter正则表达式有什么作用? 答:提取请求中返回的数据, 然后获取的数据放入其 ...

  3. JavaScript学习03(函数)

    函数 函数定义 JavaScript 函数是通过 function 关键词定义的. 声明定义 function functionName(parameters) { 要执行的代码 } 被声明的函数不会 ...

  4. Python之简单的神经网络

    from sklearn import datasets from sklearn import preprocessing from sklearn.model_selection import t ...

  5. sqli-labs lesson 32-37

    宽字节注入: 原理:mysql在使用GBK编码的时候,会认为两个字符为一个汉字,例如%aa%5c就是一个汉字(前一个ascii码大于128才能到汉字的范围).我们在过滤 ' 的时候(也就是从防御的角度 ...

  6. DVWA靶场之File Upload(文件上传)通关

    Low: <?php if( isset( $_POST[ 'Upload' ] ) ) { // Where are we going to be writing to? $target_pa ...

  7. STM32—ADC详解

    文章目录 一.ADC简介 二.ADC功能框图讲解 1.电压输入范围 2.输入通道 3.转换顺序 4.触发源 5.转换时间 6.数据寄存器 7.中断 8.电压转换 三.初始化结构体 四.单通道电压采集 ...

  8. .NET 6 全新指标 System.Diagnostics.Metrics 介绍

    前言 工友们, .NET 6 Preview 7 已经在8月10号发布了, 除了众多的功能更新和性能改进之外, 在 preview 7 版本中, 也新增了全新的指标API, System.Diagno ...

  9. CPU 指令环 ring0,ring1,ring2,ring3

    Intel的CPU将特权级别分为4个级别:RING0,RING1,RING2,RING3. Windows只使用其中的两个级别RING0和RING3,RING0只给操作系统用,RING3谁都能用.如果 ...

  10. Linux+Apache+Mysql+PHP简单的测试环境搭建

    系统版本为:Linux localhost.localdomain 2.6.32-431.el6.x86_64 #1 SMP Fri Nov 22 03:15:09 UTC 2013 x86_64 x ...