1
0
mirror of https://github.com/Snailclimb/JavaGuide synced 2025-06-16 18:10:13 +08:00

完善redis bitmap 数据结构的描述

This commit is contained in:
guide 2021-03-08 20:51:29 +08:00
parent abaf40fdbd
commit 88aa853d97

View File

@ -16,11 +16,12 @@
- [6.3. hash](#63-hash)
- [6.4. set](#64-set)
- [6.5. sorted set](#65-sorted-set)
- [6.6 bitmap](#66-bitmap)
- [7. Redis 单线程模型详解](#7-redis-单线程模型详解)
- [8. Redis 没有使用多线程?为什么不使用多线程?](#8-redis-没有使用多线程为什么不使用多线程)
- [9. Redis6.0 之后为何引入了多线程?](#9-redis60-之后为何引入了多线程)
- [10. Redis 给缓存数据设置过期时间有啥用?](#10-redis-给缓存数据设置过期时间有啥用)
- [11. Redis是如何判断数据是否过期的呢?](#11-redis是如何判断数据是否过期的呢)
- [11. Redis 是如何判断数据是否过期的呢?](#11-redis-是如何判断数据是否过期的呢)
- [12. 过期的数据的删除策略了解么?](#12-过期的数据的删除策略了解么)
- [13. Redis 内存淘汰机制了解么?](#13-redis-内存淘汰机制了解么)
- [14. Redis 持久化机制(怎么保证 Redis 挂掉之后再重启数据可以进行恢复)](#14-redis-持久化机制怎么保证-redis-挂掉之后再重启数据可以进行恢复)
@ -32,13 +33,14 @@
- [17. 缓存雪崩](#17-缓存雪崩)
- [17.1. 什么是缓存雪崩?](#171-什么是缓存雪崩)
- [17.2. 有哪些解决办法?](#172-有哪些解决办法)
- [18. 如何保证缓存与数据库双写时的数据一致性?](#18-如何保证缓存与数据库双写时的数据一致性)
- [18. 如何保证缓存和数据库数据的一致性?](#18-如何保证缓存和数据库数据的一致性)
- [19. 参考](#19-参考)
- [20. 公众号](#20-公众号)
<!-- /code_chunk_output -->
### 1. 简单介绍一下 Redis 呗!
简单来说 **Redis 就是一个使用 C 语言开发的数据库**,不过与传统数据库不同的是 **Redis 的数据是存在内存中的** ,也就是它是内存数据库,所以读写速度非常快,因此 Redis 被广泛应用于缓存方向。
@ -311,7 +313,6 @@ OK
1) "value2"
```
#### 6.5. sorted set
1. **介绍:** 和 set 相比sorted set 增加了一个权重参数 score使得集合中的元素能够按 score 进行有序排列,还可以通过 score 的范围来获取元素的列表。有点像是 Java 中 HashMap 和 TreeSet 的结合体。
@ -339,39 +340,52 @@ OK
2) "value2"
```
#### 6.6 bitMap
#### 6.6 bitmap
**1、BitMap是什么**
就是通过一个bit位来表示某个元素对应的值或者状态,其中的key就是对应元素本身。我们知道8个bit可以组成一个Byte所以bitmap本身会极大的节省储存空间。
**2、Redis中的BitMap**
Redis从2.2.0版本开始新增了setbit,getbit,bitcount等几个bitmap相关命令。虽然是新命令但是并没有新增新的数据类型因为setbit等命令只不过是在set上的扩展。
**3、setbit命令介绍**
指令 SETBIT key offset value
设置或者清空key的value(字符串)在offset处的bit值(只能只0或者1)。
**4、使用场景一用户签到**
很多网站都提供了签到功能(这里不考虑数据落地事宜)并且需要展示最近一个月的签到情况如果使用bitmap我们怎么做
根据日期 offset =hash % 365 key = 年份#用户id
1. **介绍 ** bitmap 存储的是连续的二进制数字0 和 1通过 bitmap, 只需要一个 bit 位来表示某个元素对应的值或者状态key 就是对应元素本身 。我们知道 8 个 bit 可以组成一个 byte所以 bitmap 本身会极大的节省储存空间。
2. **常用命令:** `setbit``getbit``bitcount``bitop`
3. **应用场景:** 适合需要保存状态信息(比如是否签到、是否登录...)并需要进一步对这些信息进行分析的场景。比如用户签到情况、活跃用户情况、用户行为统计(比如是否点赞过某个视频)。
```bash
127.0.0.1:6379> setbit 2021#codinglemon 1 1
# SETBIT 会返回之前位的值(默认是 0这里会生成 7 个位
127.0.0.1:6379> setbit mykey 7 1
(integer) 0
127.0.0.1:6379> setbit 2021#codinglemon 2 1
127.0.0.1:6379> setbit mykey 7 0
(integer) 1
127.0.0.1:6379> getbit mykey 7
(integer) 0
127.0.0.1:6379> bitcount 2021#codinglemon
127.0.0.1:6379> setbit mykey 6 1
(integer) 0
127.0.0.1:6379> setbit mykey 8 1
(integer) 0
# 通过 bitcount 统计被被设置为 1 的位的数量。
127.0.0.1:6379> bitcount mykey
(integer) 2
```
**5、使用场景二统计活跃用户**
使用时间作为cacheKey然后用户ID为offset如果当日活跃过就设置为1
那么我该如果计算某几天/月/年的活跃用户呢(暂且约定,统计时间内只有有一天在线就称为活跃)有请下一个redis的命令
命令 BITOP operation destkey key [key ...]
说明:对一个或多个保存二进制位的字符串 key 进行位元操作,并将结果保存到 destkey 上。
说明BITOP 命令支持 AND 、 OR 、 NOT 、 XOR 这四种操作中的任意一种参数
针对上面提到的一些场景,这里进行进一步说明。
20210308 活跃用户 【12】
20210309 活跃用户 【1】
统计20210308~20210309 总活跃用户数: 1
**使用场景一:用户行为分析**
很多网站为了分析你的喜好,需要研究你点赞过的内容。
```bash
# 记录你喜欢过 001 号小姐姐
127.0.0.1:6379> setbit beauty_girl_001 uid 1
```
**使用场景二:统计活跃用户**
使用时间作为 key然后用户 ID 为 offset如果当日活跃过就设置为 1
那么我该如果计算某几天/月/年的活跃用户呢(暂且约定,统计时间内只有有一天在线就称为活跃),有请下一个 redis 的命令
```bash
# 对一个或多个保存二进制位的字符串 key 进行位元操作,并将结果保存到 destkey 上。
# BITOP 命令支持 AND 、 OR 、 NOT 、 XOR 这四种操作中的任意一种参数
BITOP operation destkey key [key ...]
```
初始化数据:
```bash
127.0.0.1:6379> setbit 20210308 1 1
@ -380,6 +394,11 @@ Redis从2.2.0版本开始新增了setbit,getbit,bitcount等几个bitmap相关命
(integer) 0
127.0.0.1:6379> setbit 20210309 1 1
(integer) 0
```
统计 20210308~20210309 总活跃用户数: 1
```bash
127.0.0.1:6379> bitop and desk1 20210308 20210309
(integer) 1
127.0.0.1:6379> bitcount desk1
@ -395,11 +414,11 @@ Redis从2.2.0版本开始新增了setbit,getbit,bitcount等几个bitmap相关命
(integer) 2
```
**6、使用场景三用户在线状态**
对于获取或者统计用户在线状态,
使用bitmap是一个节约空间效率又高的一种方法只需要一个key然后用户ID为offset如果在线就设置为1
不在线就设置为0和上面的场景一样5000W用户只需要6MB的空间。
**使用场景三:用户在线状态**
对于获取或者统计用户在线状态,使用 bitmap 是一个节约空间效率又高的一种方法。
只需要一个 key然后用户 ID 为 offset如果在线就设置为 1不在线就设置为 0。
### 7. Redis 单线程模型详解
@ -425,10 +444,10 @@ Redis 通过**IO 多路复用程序** 来监听来自客户端的大量连接(
可以看出文件事件处理器file event handler主要是包含 4 个部分:
* 多个 socket客户端连接
* IO 多路复用程序(支持多个客户端连接的关键)
* 文件事件分派器(将 socket 关联到相应的事件处理器)
* 事件处理器(连接应答处理器、命令请求处理器、命令回复处理器)
- 多个 socket客户端连接
- IO 多路复用程序(支持多个客户端连接的关键)
- 文件事件分派器(将 socket 关联到相应的事件处理器)
- 事件处理器(连接应答处理器、命令请求处理器、命令回复处理器)
![](images/redis-all/redis事件处理器.png)
@ -760,11 +779,11 @@ Cache Aside Pattern 中遇到写请求是这样的:更新 DB然后直接删
### 19. 参考
* 《Redis 开发与运维》
* 《Redis 设计与实现》
* Redis 命令总结http://Redisdoc.com/string/set.html
* 通俗易懂的 Redis 数据结构基础教程:[https://juejin.im/post/5b53ee7e5188251aaa2d2e16](https://juejin.im/post/5b53ee7e5188251aaa2d2e16)
* WHY Redis choose single thread (vs multi threads): [https://medium.com/@jychen7/sharing-redis-single-thread-vs-multi-threads-5870bd44d153](https://medium.com/@jychen7/sharing-redis-single-thread-vs-multi-threads-5870bd44d153)
- 《Redis 开发与运维》
- 《Redis 设计与实现》
- Redis 命令总结http://Redisdoc.com/string/set.html
- 通俗易懂的 Redis 数据结构基础教程:[https://juejin.im/post/5b53ee7e5188251aaa2d2e16](https://juejin.im/post/5b53ee7e5188251aaa2d2e16)
- WHY Redis choose single thread (vs multi threads): [https://medium.com/@jychen7/sharing-redis-single-thread-vs-multi-threads-5870bd44d153](https://medium.com/@jychen7/sharing-redis-single-thread-vs-multi-threads-5870bd44d153)
### 20. 公众号