Redis是什么?
Redis(Remote Dictionary Server ),即远程字典服务。
是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。
与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。
Redis能该干什么?
- 内存存储、持久化,内存是断电即失的,所以需要持久化(RDB、AOF)
- 高效率、用于高速缓冲
- 发布订阅系统
- 地图信息分析
- 计时器、计数器(eg:浏览量)
- 。。。
特性
- 多样的数据类型
- 持久化
- 集群
- 事务
Linux环境搭建
1.下载安装包
输入对应的版本号下载不同版本
https://download.redis.io/releases/redis-6.2.6.tar.gz
2.将下载的安装包放到/opt目录下
3.解压安装包
4.安装依赖的环境
yum install gcc-c++# 然后进入redis目录下执行cd /opt/redis-5.0.8makemake install
出现以下画面代表成功
5.确认redis默认安装路径 /usr/local/bin
6.复制配置文件到kconfig(此目录手动创建用于存放redis配置文件)
cp /opt/redis-5.0.8/redis.conf /usr/local/bin/kconfig/
7.修改配置文件
# Accept connections on the specified port, default is 6379 (IANA #815344).
# If port 0 is specified Redis will not listen on a TCP socket.
#配置端口号
port 8066
# By default Redis does not run as a daemon. Use 'yes' if you need it.
# Note that Redis will write a pid file in /var/run/redis.pid when daemonized.
#设置后台启动
daemonize yes
8.启动redis服务
#redis-server 指定配置文件地址
[root@b904e77355ae bin]# redis-server /usr/local/bin/kconfig/redis.conf
4419:C 29 Oct 2021 00:54:08.296 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
4419:C 29 Oct 2021 00:54:08.298 # Redis version=5.0.8, bits=64, commit=00000000, modified=0, pid=4419, just started
4419:C 29 Oct 2021 00:54:08.298 # Configuration loaded
Redis性能测试
redis-benchmark:Redis官方提供的性能测试工具,参数选项如下:
# 测试:100个并发连接 100000请求
redis-benchmark -h localhost -p 6379 -c 100 -n 100000
基础知识
redis默认有16个数据库
默认使用的第0个;
16个数据库为:DB 0~DB 15
默认使用DB 0 ,可以使用select n切换到DB n,dbsize可以查看当前数据库的大小,与key数量相关。
127.0.0.1:6379> config get databases # 命令行查看数据库数量databases
1) "databases"
2) "16"
127.0.0.1:6379> select 8 # 切换数据库 DB 8
OK
127.0.0.1:6379[8]> dbsize # 查看数据库大小
(integer) 0
# 不同数据库之间 数据是不能互通的,并且dbsize 是根据库中key的个数。
127.0.0.1:6379> set name sakura
OK
127.0.0.1:6379> SELECT 8
OK
127.0.0.1:6379[8]> get name # db8中并不能获取db0中的键值对。
(nil)
127.0.0.1:6379[8]> DBSIZE
(integer) 0
127.0.0.1:6379[8]> SELECT 0
OK
127.0.0.1:6379> keys *
1) "counter:__rand_int__"
2) "mylist"
3) "name"
4) "key:__rand_int__"
5) "myset:__rand_int__"
127.0.0.1:6379> DBSIZE # size和key个数相关
(integer) 5
keys * :查看当前数据库中所有的key。
flushdb:清空当前数据库中的键值对。
flushall:清空所有数据库的键值对。
Redis是单线程的,Redis是基于内存操作的。
所以Redis的性能瓶颈不是CPU,而是机器内存和网络带宽。
那么为什么Redis的速度如此快呢,性能这么高呢?QPS达到10W+
Redis为什么单线程还这么快?
误区1:高性能的服务器一定是多线程的?
误区2:多线程(CPU上下文会切换!)一定比单线程效率高!
核心:Redis是将所有的数据放在内存中的,所以说使用单线程去操作效率就是最高的,多线程(CPU上下文会切换:耗时的操作!),对于内存系统来说,如果没有上下文切换效率就是最高的,多次读写都是在一个CPU上的,在内存存储数据情况下,单线程就是最佳的方案。
五大数据类型
Redis是一个开源(BSD许可),内存存储的数据结构服务器,可用作数据库,高速缓存和消息队列代理。它支持字符串、哈希表、列表、集合、有序集合,位图,hyperloglogs等数据类型。内置复制、Lua脚本、LRU收回、事务以及不同级别磁盘持久化功能,同时通过Redis Sentinel提供高可用,通过Redis Cluster提供自动分区。
Redis-key
在redis中无论什么数据类型,在数据库中都是以key-value形式保存,通过进行对Redis-key的操作,来完成对数据库中数据的操作。
在redis中无论什么数据类型,在数据库中都是以key-value形式保存,通过进行对Redis-key的操作,来完成对数据库中数据的操作。
下面学习的命令:
- exists key:判断键是否存在
- del key:删除键值对
- move key db:将键值对移动到指定数据库
- expire key second:设置键值对的过期时间
- type key:查看value的数据类型 ```shell 127.0.0.1:6379> keys # 查看当前数据库所有key (empty list or set) 127.0.0.1:6379> set name qinjiang # set key OK 127.0.0.1:6379> set age 20 OK 127.0.0.1:6379> keys 1) “age” 2) “name” 127.0.0.1:6379> move age 1 # 将键值对移动到指定数据库 (integer) 1 127.0.0.1:6379> EXISTS age # 判断键是否存在 (integer) 0 # 不存在 127.0.0.1:6379> EXISTS name (integer) 1 # 存在 127.0.0.1:6379> SELECT 1 OK 127.0.0.1:6379[1]> keys * 1) “age” 127.0.0.1:6379[1]> del age # 删除键值对 (integer) 1 # 删除个数
127.0.0.1:6379> set age 20 OK 127.0.0.1:6379> EXPIRE age 15 # 设置键值对的过期时间
(integer) 1 # 设置成功 开始计数 127.0.0.1:6379> ttl age # 查看key的过期剩余时间 (integer) 13 127.0.0.1:6379> ttl age (integer) 11 127.0.0.1:6379> ttl age (integer) 9 127.0.0.1:6379> ttl age (integer) -2 # -2 表示key过期,-1表示key未设置过期时间
127.0.0.1:6379> get age # 过期的key 会被自动delete (nil) 127.0.0.1:6379> keys * 1) “name”
127.0.0.1:6379> type name # 查看value的数据类型 string
关于TTL命令<br />Redis的key,通过TTL命令返回key的过期时间,一般来说有3种:
1. 当前key没有设置过期时间,所以会返回-1.
1. 当前key有设置过期时间,而且key已经过期,所以会返回-2.
1. 当前key有设置过期时间,且key还没有过期,故会返回key的正常剩余时间.
关于重命名RENAME和RENAMENX
- RENAME key newkey修改 key 的名称
- RENAMENX key newkey仅当 newkey 不存在时,将 key 改名为 newkey 。
更多命令学习:[https://www.redis.net.cn/order/](https://www.redis.net.cn/order/)
<a name="TuIdP"></a>
## String(字符串)
```shell
##########################################################################
127.0.0.1:6379> set key1 v1 # 设置值
OK
127.0.0.1:6379> get key1 # 获得值
"v1"
127.0.0.1:6379> keys * # 获得所有的key
1) "key1"
127.0.0.1:6379> EXISTS key1 # 判断某一个key是否存在
(integer) 1
127.0.0.1:6379> APPEND key1 "hello" # 追加字符串,如果当前key不存在,就相当于setkey
(integer) 7
127.0.0.1:6379> get key1
"v1hello"
127.0.0.1:6379> STRLEN key1 # 获取字符串的长度!
(integer) 7
127.0.0.1:6379> APPEND key1 ",kaungshen"
(integer) 17
127.0.0.1:6379> STRLEN key1
(integer) 17
127.0.0.1:6379> get key1
"v1hello,kaungshen"
##########################################################################
# i++
# 步长 i+=
127.0.0.1:6379> set views 0 # 初始浏览量为0
OK
127.0.0.1:6379> get views
"0"
127.0.0.1:6379> incr views #自增1
(integer) 1
127.0.0.1:6379> incr views
(integer) 2
127.0.0.1:6379> get views
"2"
127.0.0.1:6379> decr views #自减1
(integer) 1
127.0.0.1:6379> decr views
(integer) 0
127.0.0.1:6379> decr views
(integer) -1
127.0.0.1:6379> get views
"-1"
127.0.0.1:6379> INCRBY views 10 # 可以设置步长,指定增量!-自增10
(integer) 9
127.0.0.1:6379> INCRBY views 10
(integer) 19
127.0.0.1:6379> DECRBY views 5 #自减5
(integer) 14
##########################################################################
# 字符串范围 range
127.0.0.1:6379> set key1 "hello,kuangshen" # 设置 key1 的值
OK
127.0.0.1:6379> get key1
"hello,kuangshen"
127.0.0.1:6379> GETRANGE key1 0 3 # 截取字符串 [0,3]
"hell"
127.0.0.1:6379> GETRANGE key1 0 -1 # 获取全部的字符串 和 get key是一样的
"hello,kuangshen"
# 替换!
127.0.0.1:6379> set key2 abcdefg
OK
127.0.0.1:6379> get key2
"abcdefg"
127.0.0.1:6379> SETRANGE key2 1 xx #替换指定位置的字符串
(integer) 7
127.0.0.1:6379> get key2
"axxdefg"
##########################################################################
# setex (set with expire) # 设置过期时间
# setnx (set if not exist) # 不存在在设置 (在分布式锁中会常常使用!)
127.0.0.1:6379> setex key3 30 "hello" # 设置key3 的值为 hello,30秒后过期
OK
127.0.0.1:6379> ttl key3
(integer) 26
127.0.0.1:6379> get key3
"hello"
127.0.0.1:6379> setnx mykey "redis" #如果mykey不存在则创建mykey
(integer) 1
127.0.0.1:6379> keys *
1) "key2"
2) "mykey"
3) "key1"
127.0.0.1:6379> ttl key3
(integer) -2
127.0.0.1:6379> setnx mykey "MongoDB" #mykey存在,创建失败
(integer) 0
127.0.0.1:6379> get mykey
"redis"
##########################################################################
mset
mget
127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3 # 同时设置多个值
OK
127.0.0.1:6379> keys *
1) "k1"
2) "k2"
3) "k3"
127.0.0.1:6379> mget k1 k2 k3 # 同时获取多个值
1) "v1"
2) "v2"
3) "v3"
127.0.0.1:6379> msetnx k1 v1 k4 v4 # msetnx 是一个原子性的操作,要么一起成功,要么一起 失败!
(integer) 0
127.0.0.1:6379> get k4
(nil)
# 对象
set user:1 {name:zhangsan,age:3} # 设置一个user:1 对象 值为 json字符来保存一个对象!
# 这里的key是一个巧妙的设计: user:{id}:{filed} , 如此设计在Redis中是完全OK了!
127.0.0.1:6379> mset user:1:name zhangsan user:1:age 2
OK
127.0.0.1:6379> mget user:1:name user:1:age
1) "zhangsan"
2) "2"
##########################################################################
getset # 先get然后在set
127.0.0.1:6379> getset db redis # 如果不存在值,则返回 nil (nil)
127.0.0.1:6379> get db
"redis"
127.0.0.1:6379> getset db mongodb # 如果存在值,获取原来的值,并设置新的值 "redis"
127.0.0.1:6379> get db
"mongodb"
数据结构是相同的! String类似的使用场景:value除了是我们的字符串还可以是我们的数字!
localhost:8066> LPUSH list one
(integer) 1
localhost:8066> LPUSH list two
(integer) 2
localhost:8066> LPUSH list three
(integer) 3
localhost:8066> LRANGE list 0 -1
1) "three"
2) "two"
3) "one"
localhost:8066> LRANGE list 0 1
1) "three"
2) "two"
localhost:8066> LRANGE list 0 0
1) "three"
localhost:8066> RPUSH list right
(integer) 4
localhost:8066> LRANGE list 0 -1
1) "three"
2) "two"
3) "one"
4) "right"
localhost:8066> LPOP list
"three"
localhost:8066> RPOP list
"right"
localhost:8066> LRANGE list 0 -1
1) "two"
2) "one"
localhost:8066> LINDEX list 1
"one"
localhost:8066> LINDEX list 0
"two"
localhost:8066> LPUSH list three
(integer) 3
localhost:8066> LPUSH list three
(integer) 4
localhost:8066> LRANGE list 0 -1
1) "three"
2) "three"
3) "two"
4) "one"
localhost:8066> LREM list 1 one
(integer) 1
localhost:8066> LRANGE list 0 -1
1) "three"
2) "three"
3) "two"
localhost:8066> LREM list 2 three
(integer) 2
localhost:8066> LRANGE list 0 -1
1) "two"
localhost:8066> RPUSH list "hello" "hello1"
(integer) 2
localhost:8066> LRANGE list 0 -1
1) "hello"
2) "hello1"
localhost:8066> RPUSH list "hello2" "hello3"
(integer) 4
localhost:8066> LRANGE list 0 -1
1) "hello"
2) "hello1"
3) "hello2"
4) "hello3"
localhost:8066> LTRIM list 1 2
OK
localhost:8066> LRANGE list 0 -1
1) "hello1"
2) "hello2"
localhost:8066> RPOPLPUSH list list2
"hello2"
localhost:8066> LRANGE list 0 -1
1) "hello1"
localhost:8066> LRANGE list2 0 -1
1) "hello2"
localhost:8066> EXISTS list3
(integer) 0
localhost:8066> LSET list3 0 item
(error) ERR no such key
localhost:8066> LPUSH list3 test
(integer) 1
localhost:8066> LRANGE list3 0 -1
1) "test"
localhost:8066> LSET list3 0 item
OK
localhost:8066> LRANGE list3 0 -1
1) "item"
localhost:8066> LRANGE list3 1 test2
(error) ERR value is not an integer or out of range
localhost:8066> RPUSH list hello world
(integer) 2
localhost:8066> LRANGE list 0 -1
1) "hello"
2) "world"
localhost:8066> LINSERT list before world test
(integer) 3
localhost:8066> LRANGE list 0 -1
1) "hello"
2) "test"
3) "world"
localhost:8066> LINSERT list after world test2
(integer) 4
localhost:8066> LRANGE list 0 -1
1) "hello"
2) "test"
3) "world"
4) "test2"
Set(集合)
localhost:8066> sadd myset hello zeng test
(integer) 3
localhost:8066> SMEMBERS myset
1) "test"
2) "zeng"
3) "hello"
localhost:8066> SISMEMBER myset zeng
(integer) 1
localhost:8066> SISMEMBER myset hui
(integer) 0
localhost:8066> SCARD myset
(integer) 3
localhost:8066> sadd myset zeng
(integer) 0
localhost:8066> sadd myset zeng1
(integer) 1
localhost:8066> SCARD myset
(integer) 4
localhost:8066> SMEMBERS myset
1) "zeng1"
2) "test"
3) "zeng"
4) "hello"
localhost:8066> srem myset zeng1
(integer) 1
localhost:8066> SMEMBERS myset
1) "test"
2) "zeng"
3) "hello"
localhost:8066> SRANDMEMBER myset 1
1) "test"
localhost:8066> SRANDMEMBER myset 1
1) "hello"
localhost:8066> SRANDMEMBER myset 1
1) "hello"
localhost:8066> SMOVE myset myset2 zeng
(integer) 1
localhost:8066> SMEMBERS myset2
1) "zeng"
localhost:8066> sadd myset a b c
(integer) 3
localhost:8066> sadd myset2 c d e
(integer) 3
localhost:8066> sdiff myset myset2
1) "b"
2) "a"
localhost:8066> SINTER myset myset2
1) "c"
localhost:8066> SUNION myset myset2
1) "c"
2) "d"
3) "b"
4) "a"
5) "e"
Hash
localhost:8066> hset test key1 value1
(integer) 1
localhost:8066> hget test key1
"value1"
localhost:8066> HMSET test key1 value1 key2 value2 key3 value3
OK
localhost:8066> HGETALL test
1) "key1"
2) "value1"
3) "key2"
4) "value2"
5) "key3"
6) "value3"
localhost:8066> HDEL test key2
(integer) 1
localhost:8066> HGETALL test
1) "key1"
2) "value1"
3) "key3"
4) "value3"
localhost:8066> HLEN test
(integer) 2
localhost:8066> HEXISTS test key1
(integer) 1
localhost:8066> HEXISTS test key2
(integer) 0
localhost:8066> HEXISTS test key3
(integer) 1
localhost:8066> HGETALL test
1) "key1"
2) "value1"
3) "key3"
4) "value3"
localhost:8066> HVALS test
1) "value1"
2) "value3"
localhost:8066> HKEYS test
1) "key1"
2) "key3"
localhost:8066> hset test key2 10
(integer) 1
localhost:8066> HGETALL test
1) "key1"
2) "value1"
3) "key3"
4) "value3"
5) "key2"
6) "10"
localhost:8066> HINCRBY test key2 10
(integer) 20
localhost:8066> HGETALL test
1) "key1"
2) "value1"
3) "key3"
4) "value3"
5) "key2"
6) "20"
localhost:8066> HSETNX test key4 aa
(integer) 1
localhost:8066> HSETNX test key4 aa
(integer) 0
localhost:8066> HGETALL test
1) "key1"
2) "value1"
3) "key3"
4) "value3"
5) "key2"
6) "20"
7) "key4"
8) "aa"
ZSET(有序集合)
localhost:8066> ZADD test 1 aaa 2 bbb 4 ddd 3 ccc
(integer) 4
localhost:8066> ZRANGE test 0 -1
1) "aaa"
2) "bbb"
3) "ccc"
4) "ddd"
localhost:8066> ZRANGEBYSCORE test -inf +inf
1) "aaa"
2) "bbb"
3) "ccc"
4) "ddd"
localhost:8066> ZRANGEBYSCORE test 1 10 withscores
1) "aaa"
2) "1"
3) "bbb"
4) "2"
5) "ccc"
6) "3"
7) "ddd"
8) "4"
localhost:8066> ZRANGEBYSCORE test 1 3 withscores
1) "aaa"
2) "1"
3) "bbb"
4) "2"
5) "ccc"
6) "3"
localhost:8066> ZRANGE test 0 -1
1) "aaa"
2) "bbb"
3) "ccc"
4) "ddd"
localhost:8066> zrem test bbb
(integer) 1
localhost:8066> ZRANGE test 0 -1
1) "aaa"
2) "ccc"
3) "ddd"
localhost:8066> ZREVRANGE test 0 -1
1) "ddd"
2) "ccc"
3) "aaa"
localhost:8066> ZCOUNT test 0 1
(integer) 1
localhost:8066> ZCOUNT test 0 2
(integer) 1
localhost:8066> ZCOUNT test 0 3
(integer) 2
localhost:8066> ZCOUNT test 0 4
(integer) 3
localhost:8066> ZCOUNT test 0 5
(integer) 3
特殊数据类型
geospatial 地理位置

http://www.jsons.cn/lngcodeinfo/0706D99C19A781A3/
官方文档:https://www.redis.net.cn/order/3685.html
GEOADD 添加地理数据
127.0.0.1:6379> geoadd china:city 116.40 39.90 beijing
(integer) 1
127.0.0.1:6379> geoadd china:city 121.47 31.23 shanghai
(integer) 1
127.0.0.1:6379> geoadd china:city 106.50 29.53 chongqi 114.05 22.52 shengzhen (integer) 2
127.0.0.1:6379> geoadd china:city 120.16 30.24 hangzhou 108.96 34.26 xian (integer) 2
GEOPOS 返回指定地点的坐标值
127.0.0.1:6379> GEOPOS china:city beijing # 获取指定的城市的经度和纬度! 1) 1) "116.39999896287918091"
2) "39.90000009167092543"
127.0.0.1:6379> GEOPOS china:city beijing chongqi
1) 1) "116.39999896287918091"
2) "39.90000009167092543"
2) 1) "106.49999767541885376"
2) "29.52999957900659211"
GEODIST 计算两个点之间的距离
单位:m 表示单位为米。 km 表示单位为千米。 mi 表示单位为英里。 ft 表示单位为英尺。
127.0.0.1:6379> GEODIST china:city beijing shanghai km # 查看上海到北京的直线距离 "1067.3788"
127.0.0.1:6379> GEODIST china:city beijing chongqi km # 查看重庆到北京的直线距离 "1464.0708"
GEORADIUS 以给定的经纬度为中心, 找出某一半径内的元素
127.0.0.1:6379> GEORADIUS china:city 110 30 1000 km # 以110,30 这个经纬度为中心,寻 找方圆1000km内的城市
1) "chongqi"
2) "xian"
3) "shengzhen"
4) "hangzhou"
127.0.0.1:6379> GEORADIUS china:city 110 30 500 km
1) "chongqi"
2) "xian"
127.0.0.1:6379> GEORADIUS china:city 110 30 500 km withdist withdist # 显示到中间距离的位置
1) 1) "chongqi"
2) "341.9374"
2) 1) "xian"
2) "483.8340"
127.0.0.1:6379> GEORADIUS china:city 110 30 500 km withcoord withcoord # 显示他人的定位信息
1) 1) "chongqi"
2) 1) "106.49999767541885376"
2) "29.52999957900659211"
2) 1) "xian"
2) 1) "108.96000176668167114"
2) "34.25999964418929977"
127.0.0.1:6379> GEORADIUS china:city 110 30 500 km withdist withcoord count 1 # 筛选出指定的结果!
1) 1) "chongqi"
2) "341.9374"
3) 1) "106.49999767541885376"
2) "29.52999957900659211"
127.0.0.1:6379> GEORADIUS china:city 110 30 500 km withdist withcoord count 2
1) 1) "chongqi"
2) "341.9374"
3) 1) "106.49999767541885376"
2) "29.52999957900659211"
2) 1) "xian"
2) "483.8340"
3) 1) "108.96000176668167114"
2) "34.25999964418929977"
GEORADIUSBYMEMBER 查询指定位置周围有哪些地址
# 找出位于指定元素周围的其他元素!
127.0.0.1:6379> GEORADIUSBYMEMBER china:city beijing 1000 km 1) "beijing"
2) "xian"
127.0.0.1:6379> GEORADIUSBYMEMBER china:city shanghai 400 km 1) "hangzhou"
2) "shanghai"
GEOHASH - 将指定位置的经纬度转换我geohash格式

# 将二维的经纬度转换为一维的字符串,如果两个字符串越接近,那么则距离越近! 127.0.0.1:6379> geohash china:city beijing chongqi
1) "wx4fbxxfke0"
2) "wm5xzrybty0"
GEO 底层的实现原理其实就是 Zset!我们可以使用Zset命令来操作geo!
127.0.0.1:6379> ZRANGE china:city 0 -1 # 查看地图中全部的元素 1) "chongqi"
2) "xian"
3) "shengzhen"
4) "hangzhou"
5) "shanghai"
6) "beijing"
127.0.0.1:6379> zrem china:city beijing # 移除指定元素! (integer) 1
127.0.0.1:6379> ZRANGE china:city 0 -1
1) "chongqi"
2) "xian"
3) "shengzhen"
4) "hangzhou"
5) "shanghai"
Hyperloglog 基数统计
基数-数组中不重复的元素个数
A {1,3,5,7,8,7}
6个元素,不重复的有5个,基数是5
B {1,3,5,7,8}
基数为5
优点:占用的内存是固定,2^64 不同的元素的技术,只需要废 12KB内存!如果要从内存角度来比较的 话 Hyperloglog 首选!
网页的 UV (一个人访问一个网站多次,但是还是算作一个人!)
传统的方式, set 保存用户的id,然后就可以统计 set 中的元素数量作为标准判断 ! 这个方式如果保存大量的用户id,就会比较麻烦!我们的目的是为了计数,而不是保存用户id; 0.81% 错误率! 统计UV任务,可以忽略不计的!
127.0.0.1:6379> PFadd mykey a b c d e f g h i j # 创建第一组元素 mykey (integer) 1
127.0.0.1:6379> PFCOUNT mykey # 统计 mykey 元素的基数数量
(integer) 10
127.0.0.1:6379> PFadd mykey2 i j z x c v b n m # 创建第二组元素 mykey2 (integer) 1
127.0.0.1:6379> PFCOUNT mykey2
(integer) 9
127.0.0.1:6379> PFMERGE mykey3 mykey mykey2 # 合并两组 mykey mykey2 => mykey3 并集 OK
127.0.0.1:6379> PFCOUNT mykey3 # 看并集的数量!
(integer) 15
如果允许容错,那么一定可以使用 Hyperloglog ! 如果不允许容错,就使用 set 或者自己的数据类型即可!
Bitmap
位存储
统计用户信息,活跃,不活跃! 登录 、 未登录! 打卡,365打卡! 两个状态的,都可以使用 Bitmaps!
Bitmap 位图,数据结构! 都是操作二进制位来进行记录,就只有0 和 1 两个状态!
365 天 = 365 bit 1字节 = 8bit 46 个字节左右!
#使用bitmap记录一星期打卡情况,0-6代表星期一到七 0/1代表状态
localhost:8066> setbit testbmap 0 0
(integer) 0
localhost:8066> setbit testbmap 1 0
(integer) 0
localhost:8066> setbit testbmap 2 1
(integer) 0
localhost:8066> setbit testbmap 3 1
(integer) 0
localhost:8066> setbit testbmap 4 1
(integer) 0
localhost:8066> setbit testbmap 5 1
(integer) 0
localhost:8066> setbit testbmap 6 1
(integer) 0
#
localhost:8066> GETBIT testbmap 3
(integer) 1
localhost:8066> GETBIT testbmap 1
(integer) 0
localhost:8066> GETBIT testbmap 10
(integer) 0
localhost:8066> GETBIT testbmap 0
(integer) 0
#
localhost:8066> BITCOUNT testbmap
(integer) 5

