文章目录
1.nosql 概述
为什么要用Nosql
1、单机MySQL的年代!
90年代,一个基本的网站访问量一般不会太大,单个数据库完全足够!
那个时候,更多的去使用静态网页 Html ~ 服务器根本没有太大的压力!
思考一下,这种情况下:整个网站的瓶颈是什么?
1、数据量如果太大、一个机器放不下了!
2、数据的索引 (B+ Tree),一个机器内存也放不下
3、访问量(读写混合),一个服务器承受不了~
只要你开始出现以上的三种情况之一,那么你就必须要晋级!
2、Memcached(缓存) + MySQL + 垂直拆分 (读写分离)
网站80%的情况都是在读,每次都要去查询数据库的话就十分的麻烦!所以说我们希望减轻数据的压
力,我们可以使用缓存来保证效率!
发展过程: 优化数据结构和索引–> 文件缓存(IO)—> Memcached(当时最热门的技术!)
3、分库分表 + 水平拆分 + MySQL集群
技术和业务在发展的同时,对人的要求也越来越高!
本质:数据库(读,写)
早些年MyISAM: 表锁,十分影响效率!高并发下就会出现严重的锁问题
转战Innodb:行锁
慢慢的就开始使用分库分表来解决写的压力! MySQL 在哪个年代推出 了表分区!这个并没有多少公司使用!
MySQL 的 集群,很好满足哪个年代的所有需求!
4、如今最近的年代
2010–2020 十年之间,世界已经发生了翻天覆地的变化;(定位,也是一种数据,音乐,热榜!)
MySQL 等关系型数据库就不够用了!数据量很多,变化很快~!
MySQL 有的使用它来村粗一些比较大的文件,博客,图片!数据库表很大,效率就低了!如果有一种数据库来专门处理这种数据,MySQL压力就变得十分小(研究如何处理这些问题!)大数据的IO压力下,表几乎没法更大!
目前一个基本的互联网项目!
为什么要用NoSQL!
用户的个人信息,社交网络,地理位置。用户自己产生的数据,用户日志等等爆发式增长!
这时候我们就需要使用NoSQL数据库的,Nosql 可以很好的处理以上的情况!
什么是NoSQL?
NoSQL = Not Only SQL (不仅仅是SQL)
关系型数据库:表格 ,行 ,列
泛指非关系型数据库的,随着web2.0互联网的诞生!传统的关系型数据库很难对付web2.0时代!尤其是超大规模的高并发的社区! 暴露出来很多难以克服的问题,NoSQL在当今大数据环境下发展的十分迅速,Redis是发展最快的,而且是我们当下必须要掌握的一个技术!
很多的数据类型用户的个人信息,社交网络,地理位置。这些数据类型的存储不需要一个固定的格式!
不需要多月的操作就可以横向扩展的 !Map<String,Object>
使用键值对来控制!
NoSQL 特点
解耦!
1、方便扩展(数据之间没有关系,很好扩展!)
2、大数据量高性能(Redis 一秒写8万次,读取11万,NoSQL的缓存记录级,是一种细粒度的缓存,性能会比较高!)
3、数据类型是多样型的!(不需要事先设计数据库!随取随用!如果是数据量十分大的表,很多人就无法设计了!)
4、传统 RDBMS 和 NoSQL
传统的 RDBMS
- 结构化组织
- SQL
- 数据和关系都存在单独的表中 row col
- 操作操作,数据定义语言
- 严格的一致性
- 基础的事务
- …
Nosql
- 不仅仅是数据
- 没有固定的查询语言
- 键值对存储,列存储,文档存储,图形数据库(社交关系)
- 最终一致性,
- CAP定理和BASE (异地多活) 初级架构师!
- 高性能,高可用,高可扩
- …
了解:3V+3高
大数据时代的3V:主要是描述问题的
- 海量Volume
- 多样Variety
- 实时Velocity
大数据时代的3高:主要是对程序的要求
- 高并发
- 高可扩
- 高性能
真正在公司中的实践:NoSQL + RDBMS 一起使用才是最强的,阿里巴巴的架构演进!
2.阿里巴巴架构演进
如果你未来相当一个架构师: 没有什么是加一层解决不了的!
1、商品的基本信息
名称、价格、商家信息;
关系型数据库就可以解决了! MySQL / Oracle (淘宝早年就去IOE了!- 王坚:推荐文章:阿里云 的这群疯子:40分钟重要!)
淘宝内部的 MySQL 不是大家用的 MySQL
2、商品的描述、评论(文字比较多)
文档型数据库中,MongoDB
3、图片
- 分布式文件系统 FastDFS
- 淘宝自己的 TFS
- Gooale的 GFS
- Hadoop HDFS
- 阿里云的 oss
4、商品的关键字 (搜索)
- 搜索引擎 solr elasticsearch
- ISerach:多隆(多去了解一下这些技术大佬!)
所有牛逼的人都有一段苦逼的岁月!但是你只要像SB一样的去坚持,终将牛逼!
5、商品热门的波段信息 -
- 内存数据库 -
- Redis Tair、Memache…
6、商品的交易,外部的支付接口
- 三方应用
要知道,一个简单地网页背后的技术一定不是大家所想的那么简单!
大型互联网应用问题:
- 数据类型太多了!
- 数据源繁多,经常重构!
- 数据要改造,大面积改造?
解决问题:
这里以上都是NoSQL入门概述,不仅能够提高大家的知识,还可以帮助大家了解大厂的工作内容!
4.NoSQL的四大分类
KV键值对:
- 新浪:Redis
- 美团:Redis + Tair
- 阿里、百度:Redis + memecache
文档型数据库(bson格式 和json一样):
- MongoDB (一般必须要掌握)
- MongoDB 是一个基于分布式文件存储的数据库,C++ 编写,主要用来处理大量的文档!
- MongoDB 是一个介于关系型数据库和非关系型数据中中间的产MongoDB 是非关系型数据库中功能最丰富,最像关系型数据库的!
- ConthDB
列存储数据库
- HBase
- 分布式文件系统
图关系数据库
- 他不是存图形,放的是关系,比如:朋友圈社交网络,广告推荐!
- Neo4j,InfoGrid;
四者对比
5. Redis入门
(1)概述
Redis 是什么?
Redis(Remote Dictionary Server ),即远程字典服务
!
是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。
redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主-从)同步。
免费和开源!是当下最热门的 NoSQL 技术之一!也被人们称之为结构化数据库
!
Redis 能干嘛?
1、内存存储、持久化,内存中是断电即失、所以说持久化很重要(RDB、AOF)
2、效率高,可以用于高速缓存
3、发布订阅系统
4、地图信息分析
5、计时器、计数器(浏览量!)
6、…
特性
1、多样的数据类型
2、持久化
3、集群
4、事务
官网:https://redis.io/
中文官网:http://www.redis.cn/
(2)基础知识
- redis默认有16个数据库
- 默认使用的是第0个
- 可以使用
select
进行切换数据库!
127.0.0.1:6379> select 3 # 切换数据库
OK
127.0.0.1:6379[3]> DBSIZE # 查看数据库大小!
(integer) 0
127.0.0.1:6379[3]> keys * # 查看数据库所有的key)
- 清除当前数据库
flushdb
- 清除全部数据库的内容
FLUSHALL
127.0.0.1:6379[3]> flushdb
OK
127.0.0.1:6379[3]> keys *
(empty list or set)
Redis 是单线程的!
明白Redis是很快的,官方表示:Redis是基于内存操作,CPU不是Redis性能瓶颈,Redis的瓶颈是根据机器的内存和网络带宽,既然可以使用单线程来实现,就使用单线程了!
Redis 是C 语言写的,官方提供的数据为 100000+ 的QPS,完全不比同样是使用 key-vale的Memecache差!
Redis 为什么是单线程还这么快?
1、误区1:高性能的服务器一定是多线程的?
2、误区2:多线程(CPU上下文会切换!)一定比单线程效率高!
先去CPU>内存>硬盘,对这个速度要有所了解!
核心:redis 是将所有的数据全部放在内存中的,所以说使用单线程去操作效率就是最高的,多线程(CPU上下文会切换:耗时的操作!!!),对于内存系统来说,如果没有上下文切换效率就是最高的!多次读写都是在一个CPU上的,在内存情况下,这个就是最佳的方案!
6.Redis安装(Window & Linux服务器)
下载地址:通过官网下载即可!
注意:Windows版在 Github上下载(停更很久了!)
Redis推荐都是在Linux服务器上搭建的,我们是基于Linux学习!
(1)Windows安装
1、下载安装包:https://github.com/dmajkic/redis/releases
2、下载完毕得到压缩包:
3、解压到自己电脑上的环境目录下的就可以的!Redis 十分的小,只有5M
4、开启Redis,双击运行redis-server.exe
即可!
5、使用redis客户端redis-cli.exe
来连接redis
记住一句话,Window下使用确实简单,但是Redis 推荐我们使用Linux去开发使用!
(2)Linux安装
1、下载安装包! redis-5.0.8.tar.gz
2、解压Redis的安装包! 程序/opt
3、进入解压后的文件redis-5.0.8
,可以看到我们redis的配置文件
4、基本的环境安装
yum install gcc-c++
make
make install
5、redis的默认安装路径 /usr/local/bin
6、将redis配置文件,复制到我们当前目录下
7、redis默认不是后台启动的,修改配置文件!
8、启动Redis服务!
9、使用redis-cli
进行连接测试!
10、查看redis的进程是否开启!
11、如何关闭Redis服务呢? shutdown
命令
12、再次查看进程是否存在
13、后面我们会使用单机多Redis启动集群测试!
测试性能
redis-benchmark 是一个压力测试工具!
官方自带的性能测试工具!
redis-benchmark 命令参数!
图片来自菜鸟教程:
我们来简单测试下:
# 测试:100个并发连接 100000请求
redis-benchmark -h localhost -p 6379 -c 100 -n 100000
如何查看这些分析呢?
7.五大基本数据类型
官网文档
全段翻译:
Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件MQ。 它支持多种类型的数据结构,如 字符串(strings), 散列(hashes), 列表(lists), 集合(sets), 有序集合(sorted sets) 与范围查询, bitmaps, hyperloglogs 和 地理空间(geospatial) 索引半径查询。 Redis 内置了 复制(replication),LUA脚本(Lua scripting), LRU驱动事件(LRU eviction),事务(transactions) 和不同级别的 磁盘持久化(persistence), 并通过Redis哨兵(Sentinel)和自动 分区(Cluster)提供高可用性(high availability)
key pattern 查询相应的key
(1)redis允许模糊查询key 有3个通配符 *、?、[]
(2)randomkey
:返回随机key
(3)type key
:返回key存储的类型
(4)exists key
:判断某个key是否存在
(5)del key
:删除key
(6)rename key newkey
:改名
(7)renamenx key newkey
:如果newkey不存在则修改成功
(8)move key 1
:将key移动到1数据库
(9)ttl key
:查询key的生命周期(秒)
(10)expire key 整数值
:设置key的生命周期以秒为单位
(11)pexpire key 整数值
:设置key的生命周期以毫秒为单位
(12)pttl key
:查询key 的生命周期(毫秒)
(13)perisist key
:把指定key设置为永久有效
服务器相关命令
(1)ping
:测定连接是否存活
(2)echo
:在命令行打印一些内容
(3)select
:选择数据库
(4)quit
:退出连接
(5)dbsize
:返回当前数据库中key的数目
(6)info
:获取服务器的信息和统计
(7)monitor
:实时转储收到的请求
(8)config get 配置项
:获取服务器配置的信息
config set 配置项 值:设置配置项信息
(9)flushdb
:删除当前选择数据库中所有的key
(10)flushall
:删除所有数据库中的所有的key
(11)time
:显示服务器时间,时间戳(秒),微秒数
(12)bgrewriteaof
:后台保存rdb快照
(13)bgsave
:后台保存rdb快照
(14)save
:保存rdb快照
(15)lastsave
:上次保存时间
(16)shutdown [save/nosave]
:关闭Redis服务
注意:如果不小心运行了flushall
,立即shutdown nosave
,关闭服务器,然后手工编辑aof
文件,去掉文件中的flushall
相关行,然后开启服务器,就可以倒回原来是数据。如果flushall
之后,系统恰好bgwriteaof
了,那么aof
就清空了,数据丢失。
(17)showlog
:显示慢查询
问:多慢才叫慢?
答:由slowlog-log-slower-than 10000
,来指定(单位为微秒)
问:服务器存储多少条慢查询记录
答:由slowlog-max-len 128
,来做限制
实操
127.0.0.1:6379> keys * # 查看所有的key
(empty list or set)
127.0.0.1:6379> set name kuangshen # set key
OK
127.0.0.1:6379> keys *
1) "name"
127.0.0.1:6379> set age 1
OK
127.0.0.1:6379> keys *
1) "age"
2) "name"
127.0.0.1:6379> EXISTS name # 判断当前的key是否存在
(integer) 1
127.0.0.1:6379> EXISTS name1
(integer) 0
127.0.0.1:6379> move name 1 # 移除当前的key
(integer) 1
127.0.0.1:6379> keys *
1) "age"
127.0.0.1:6379> set name qinjiang
OK
127.0.0.1:6379> keys *
1) "age"
2) "name"
127.0.0.1:6379> clear
127.0.0.1:6379> keys *
1) "age"
2) "name"
127.0.0.1:6379> get name "qinjiang"
127.0.0.1:6379> EXPIRE name 10 # 设置key的过期时间,单位是秒
(integer) 1
127.0.0.1:6379> ttl name # 查看当前key的剩余时间
(integer) 4
127.0.0.1:6379> ttl name
(integer) 3
127.0.0.1:6379> ttl name
(integer) 2
127.0.0.1:6379> ttl name
(integer) 1
127.0.0.1:6379> ttl name
(integer) -2
127.0.0.1:6379> get name
(nil)
127.0.0.1:6379> type name # 查看当前key的一个类型!
string
127.0.0.1:6379> type age
string
String
90% 的 java程序员使用 redis 只会使用一个String类型!
常用命令:
(1)set key value [ex 秒数] [px 毫秒数] [nx/xx]
如果ex和px同时写,则以后面的有效期为准
nx:如果key不存在则建立
xx:如果key存在则修改其值
(2)get key
:取值
(3)mset key1 value1 key2 value2
: 一次设置多个值
(4)mget key1 key2
:一次获取多个值
(5)setrange key offset value
:把字符串的offset偏移字节改成value
如果偏移量 > 字符串长度,该字符自动补0x00
(6)append key value
:把value追加到key 的原值上
(7)getrange key start stop
:获取字符串中[start, stop]范围的值
对于字符串的下标,左数从0开始,右数从-1开始
注意:当start>length,则返回空字符串
当stop>=length,则截取至字符串尾
如果start所处位置在stop右边,则返回空字符串
(8)getset key nrevalue
:获取并返回旧值,在设置新值
(9)incr key
:自增,返回新值,如果incr一个不是int的value则返回错误,incr一个不存在的key,则设置key为1
(10)incrby key 2
:跳2自增
(11)incrbyfloat by 0.7
: 自增浮点数
(12)setbit key offset value
:设置offset对应二进制上的值,返回该位上的旧值
注意:如果offse过大,offset最大到多少?2^32-1,即可推出最大的字符串为512M
(13)bitop operation destkey key1 [key2..]
: 对key1 key2做opecation并将结果保存在destkey上
opecation可以是AND OR NOT XOR
(14)strlen key
:取指定key的value值的长度
(15)setex key time value
:设置key对应的值value,并设置有效期为time秒
数据结构是相同的!
String类似的使用场景:value除了是我们的字符串还可以是我们的数字!
- 计数器
- 统计多单位的数量
- 粉丝数
- 对象缓存存储!
List(列表)
Redis的list类型其实就是一个每个子元素都是string类型的双向链表,链表的最大长度是2^32。list既可以用做栈,也可以用做队列。
常用命令:
list的pop操作还有阻塞版本,主要是为了避免轮询
(1)lpush key value
:把值插入到链表头部
(2)rpush key value
:把值插入到链表尾部
(3)lpop key
:返回并删除链表头部元素
(4)rpop key
: 返回并删除链表尾部元素
(5)lrange key start stop
:返回链表中[start, stop]中的元素
(6)lrem key count value
:从链表中删除value值,删除count的绝对值个value后结束
count > 0 从表头删除 count < 0 从表尾删除 count=0 全部删除
(7)ltrim key start stop
:剪切key对应的链接,切[start, stop]一段并把改制重新赋给key
(8)lindex key index
:返回index索引上的值
(9)llen key
:计算链表的元素个数
(10)linsert key after|before search value
:在key 链表中寻找search,并在search值之前|之后插入value
(11)rpoplpush source dest
:把source 的末尾拿出,放到dest头部,并返回单元值
应用场景: task + bak 双链表完成安全队列
业务逻辑: rpoplpush task bak
接收返回值并做业务处理
如果成功则rpop bak清除任务,如果不成功,下次从bak表取任务
(12)brpop,blpop key timeout
:等待弹出key的尾/头元素
timeout为等待超时时间,如果timeout为0则一直等待下去
应用场景:长轮询ajax,在线聊天时能用到
在redis里面,我们可以把list
玩成 ,栈、队列、阻塞队列!
所有的list
命令都是用l
开头的,Redis不区分大小命令
小结
- 他实际上是一个链表,before Node after , left,right 都可以插入值
- 如果key 不存在,创建新的链表
- 如果key存在,新增内容
- 如果移除了所有值,空链表,也代表不存在!
- 在两边插入或者改动值,效率最高! 中间元素,相对来说效率会低一点~
Set(集合)
set中的值是不能重读的!特点:无序性、确定性、唯一性
常用命令:
(1)sadd key value1 value2
:往集合里面添加元素
(2)smembers key
:获取集合所有的元素
(3)srem key value
:删除集合某个元素
(4)spop key
:返回并删除集合中1个随机元素(可以坐抽奖,不会重复抽到某人)
(5)srandmember key
:随机取一个元素
(6)sismember key value
:判断集合是否有某个值
(7)scard key
:返回集合元素的个数
(8)smove source dest value
:把source的value移动到dest集合中
(9)sinter key1 key2 key3
:求key1 key2 key3的交集
(10)sunion key1 key2
:求key1 key2 的并集
(11)sdiff key1 key2
:求key1 key2的差集
(12)sinterstore res key1 key2
:求key1 key2的交集并存在res里
微博,A用户将所有关注的人放在一个set集合中!将它的粉丝也放在一个集合中!
共同关注,共同爱好,二度好友,推荐好友!(六度分割理论)
Hash(哈希)
Hash 是一个string类型的field和value的映射表,它的添加、删除操作都是O(1)(平均)。hash特别适用于存储对象,将一个对象存储在hash类型中会占用更少的内存,并且可以方便的存取整个对象。
配置: hash_max_zipmap_entries 64
#配置字段最多64个
hash_max_zipmap_value 512
#配置value最大为512字节
(1)hset myhash field value
:设置myhash的field为value
(2)hsetnx myhash field value
:不存在的情况下设置myhash的field为value
(3)hmset myhash field1 value1 field2 value2
:同时设置多个field
(4)hget myhash field
:获取指定的hash field
(5)hmget myhash field1 field2
:一次获取多个field
(6)hincrby myhash field 5
:指定的hash field加上给定的值
(7)hexists myhash field
:测试指定的field是否存在
(8)hlen myhash
:返回hash的field数量
(9)hdel myhash field
:删除指定的field
(10)hkeys myhash
:返回hash所有的field
(11)hvals myhash
:返回hash所有的value
(12)hgetall myhash
:获取某个hash中全部的field及value
hash变更的数据 user name age,尤其是是用户信息之类的,经常变动的信息! hash 更适合于对象的存储,String更加适合字符串存储!
Zset(有序集合)
概念:它是在set的基础上增加了一个顺序属性,这一属性在添加修改元素的时候可以指定,每次指定后,zset会自动按新的值调整顺序。可以理解为有两列的mysql表,一列存储value,一列存储顺序,操作中key理解为zset的名字。
和set一样sorted
,sets也是string类型元素的集合,不同的是每个元素都会关联一个double型的score。sorted set的实现是skip list和hash table的混合体。
当元素被添加到集合中时,一个元素到score的映射被添加到hash table中,所以给定一个元素获取score的开销是O(1)。另一个score到元素的映射被添加的skip list,并按照score排序,所以就可以有序地获取集合中的元素。添加、删除操作开销都是O(logN)和skip list
的开销一致,redis的skip list
实现是双向链表,这样就可以逆序从尾部去元素。sorted set
最经常使用方式应该就是作为索引来使用,我们可以把要排序的字段作为score存储,对象的ID当元素存储。
(1)zadd key score1 value1
:添加元素
(2)zrange key start stop [withscore]
:把集合排序后,返回名次[start,stop]的元素 默认是升续排列 withscores 是把score也打印出来
(3)zrank key member
:查询member的排名(升序0名开始)
(4)zrangebyscore key min max [withscores] limit offset N
:集合(升序)排序后取score在[min, max]内的元素,并跳过offset个,取出N个
(5)zrevrank key member
:查询member排名(降序 0名开始)
(6)zremrangebyscore key min max
:按照score来删除元素,删除score在[min, max]之间
(7)zrem key value1 value2
:删除集合中的元素
(8)zremrangebyrank key start end
:按排名删除元素,删除名次在[start, end]之间的
(9)zcard key
:返回集合元素的个数
(10)zcount key min max
:返回[min, max]区间内元素数量
(11)zinterstore dest numkeys key1[key2..] [WEIGHTS weight1 [weight2...]] [AGGREGATE SUM|MIN|MAX]
求key1,key2的交集,key1,key2的权值分别是weight1,weight2
聚合方法用 sum|min|max
聚合结果 保存子dest集合内
注意:weights,aggregate如何理解?
答:如果有交集,交集元素又有score,score怎么处理?
aggregate num->score
相加,min最小score,max最大score,另外可以通过weights设置不同的key的权重,交集时 score*weight
8.三种特殊数据类型
Geospatial 地理位置
朋友的定位,附近的人,打车距离计算?
Redis 的 Geo 在Redis3.2 版本就推出了! 这个功能可以推算地理位置的信息,两地之间的距离,方圆几里的人!
可以查询一些测试数据:http://www.jsons.cn/lngcodeinfo/0706D99C19A781A3/
只有 六个命令:
官方文档:https://www.redis.net.cn/order/3685.html
getadd
getpos:获得当前定位:一定是一个坐标值!
GEODIST:两人之间的距离!
单位:
- m 表示单位为米。
- km 表示单位为千米。
- mi 表示单位为英里。
- ft 表示单位为英尺。
georadius :以给定的经纬度为中心, 找出某一半径内的元素
我附近的人? (获得所有附近的人的地址,定位!)通过半径来查询!
获得指定数量的人,200
所有数据应该都录入:china:city ,才会让结果更加请求!
GEORADIUSBYMEMBER:找出位于指定元素周围的元素
GEOHASH 命令 - 返回一个或多个位置元素的 Geohash 表示
该命令将返回11个字符的Geohash字符串!
GEO 底层的实现原理其实就是 Zset!我们可以使用Zset命令来操作geo!
hyperloglog
什么是基数?
A {1,3,5,7,8,7}
B{1,3,5,7,8}
基数(不重复的元素) = 5,可以接受误差!
简介
Redis 2.8.9 版本就更新了 Hyperloglog 数据结构!
Redis Hyperloglog 基数统计的算法!
优点:占用的内存是固定,2^64 不同的元素的技术,只需要废 12KB内存!如果要从内存角度来比较的话 Hyperloglog 首选!
网页的 UV (一个人访问一个网站多次,但是还是算作一个人!)
传统的方式, set 保存用户的id,然后就可以统计 set 中的元素数量作为标准判断 !
这个方式如果保存大量的用户id,就会比较麻烦!我们的目的是为了计数,而不是保存用户id;0.81% 错误率! 统计UV任务,可以忽略不计的!
如果允许容错,那么一定可以使用 Hyperloglog !
如果不允许容错,就使用 set 或者自己的数据类型即可!
bitmap
位存储:
统计用户信息,活跃,不活跃! 登录 、 未登录! 打卡,365打卡! 两个状态的,都可以使用Bitmaps!Bitmap 位图,数据结构! 都是操作二进制位来进行记录,就只有0 和 1 两个状态!
365 天 = 365 bit 1字节 = 8bit 46 个字节左右!
使用bitmap 来记录 周一到周日的打卡!
周一:1 周二:0 周三:0 周四:1 …
查看某一天是否有打卡!
127.0.0.1:6379> getbit sign 3
(integer) 1
127.0.0.1:6379> getbit sign 6
(integer) 0
统计操作,统计 打卡的天数!
127.0.0.1:6379> bitcount sign # 统计这周的打卡记录,就可以看到是否有全勤!
(integer) 3