1. Redis 入门
1.1. Redis 概述
Redis:是高性能的(Key-Value)分布式内存数据库,基于内存运行,并支持持久化的NoSQL数据库
特点:
- 支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用
- 不仅支持简单的 key-value 类型的数据,同时还提供 list、set、zset、hash 等数据结构的存储
- 支持数据的备份,即 master-slave 模式的数据备份
特性:
- 持久化,多样化数据库,集群,事务...
1.2. Redis 安装(推荐 Linux 安装)---网上找教程
redis 默认不是后台启动,我们需要修改配置文件:daemonize yes
daemonize 是用来指定redis是否要用守护线程的方式启动,默认是 no
daemonize yes:当配置文件中选项 daemonize 设置成 yes 时,代表开启守护进程模式
daemonize no: 进入redis的命令行界面,exit 强制退出或者关闭连接工具都会导致 redis 进程退出
启动 redis 的服务(通过配置文件 conf 启动)
feng@feng-virtual-machine:~$ ls
公共的 模板 视频 图片 文档 下载 音乐 桌面 dump.rdb redis-7.0.11 redis-7.0.11.tar.gz snap
feng@feng-virtual-machine:~$ ps -ef|grep redis # 显示系统当前进程信息
feng 3746 3702 0 14:18 pts/1 00:00:00 grep --color=auto redis
# 启动 redis 服务
feng@feng-virtual-machine:~$ redis-server redis-7.0.11/redis.conf
# # redis客户端连接===> 观察地址的变化,如果连接ok,是直接连上的,redis默认端口号 6379
feng@feng-virtual-machine:~$ redis-cli -p 6379
127.0.0.1:6379> auth 123456
OK
127.0.0.1:6379> ping
PONG
127.0.0.1:6379> set k1 v1
OK
127.0.0.1:6379> get k1
"v1"
127.0.0.1:6379> keys *
1) "k3"
2) "k1"
3) "k2"
127.0.0.1:6379> shutdown
not connected> exit
feng@feng-virtual-machine:~$
windows系统启动redis服务:redis-server.exe
或者可以指定配置文件启动redis服务:redis-server.exe redis.windows.conf
使用 redis-cli.exe 命令启动 redis 的客户端
1.3. Redis 的基础知识
- Redis 默认有16个数据库,默认使用第 0 个
- select 2: 更换数据库2
- dbsize:查看数据库的大小
- keys *:查看数据库中所有的key
- flushdb:清空当前的数据库
- flushall:清空所有库
- 性能测试:100个并发连接,100000个请求
redis-benchmark -h localhost -p 6379 -c 100 -n 100000
1.3.1. redis 为什么是单线程?
Redis很快!!!Redis是基于内存的操作,CPU不是Redis的瓶颈,Redis的瓶颈最有可能是机器内存的大小或者网络带宽;单线程容易实现;Redis采用的是基于内存的采用的是单进程单线程模型的 K-V 数据库,由C语言编写,官方提供的数据是可以达到100000+的QPS(每秒内查询次数)
redis 为什么是单线程还是这么快?
- 高性能的服务器一定是多线程的吗?错误的
- 多线程(CPU的上下文会进行切换)一定比 单线程 效率高? 错误的
redis 核心就是如果数据全都在内存里,单线程的去操作就是效率最高的,对于一个内存的系统来说,没有上下文的切换就是效率最高的。redis 用单个CPU 绑定一块内存的数据,然后针对这块内存的数据进行多次读写的时候,都是在一个CPU上完成的,所以它是单线程处理这个事
2. Redis 的五种基本数据类型
2.1. 简要概括---String,Hash,List,Set,Zset
2.2. 字符串 String 类型
- redis最基本的类型,一个key对应一个value
- 二进制安全的,redis的string可以包含任何数据
- 一个redis中字符串 value 最多可以是 512M
- 常规 key-value 缓存应用:计数器,统计多单位的数量,对象缓存存储
# set、get、del、append、strlen
127.0.0.1:6379> set key1 value1 # 设置值
OK
127.0.0.1:6379> get key1 # 获得key
"value1"
127.0.0.1:6379> del key1 # 删除key
(integer) 1
127.0.0.1:6379> keys * # 查看全部的key
(empty list or set)
127.0.0.1:6379> exists key1 # 确保 key1 不存在
(integer) 0
127.0.0.1:6379> append key1 "hello" # 对不存在的 key 进行 append ,等同于set key1 "hello"
(integer) 5 # 字符长度
127.0.0.1:6379> append key1 "-2333" # 对已存在的字符串进行 append
(integer) 10 # 长度从 5 个字符增加到 10 个字符
127.0.0.1:6379> get key1
"hello-2333"
127.0.0.1:6379> STRLEN key1 # # 获取字符串的长度
(integer) 10
# incr、decr 一定要是数字才能进行加减,+1 和 -1。
# incrby、decrby 命令将 key 中储存的数字加上指定的增量值
127.0.0.1:6379> set views 0 # 设置浏览量为0
OK
127.0.0.1:6379> incr views # 浏览 + 1
(integer) 1
127.0.0.1:6379> decr views # 浏览 - 1
(integer) 0
127.0.0.1:6379> incrby views 10 # +10
(integer) 10
127.0.0.1:6379> decrby views 10 # -10
(integer) 0
# range [范围]
# getrange 获取指定区间范围内的值,类似between...and的关系,从0到-1表示全部
127.0.0.1:6379> set key2 abcd123456 # 设置key2的值
OK
127.0.0.1:6379> getrange key2 0 -1 # 获得全部的值
"abcd123456"
127.0.0.1:6379> getrange key2 0 2 # 截取部分字符串
"abc"
# setrange 设置指定区间范围内的值,格式是setrange key值 具体值
127.0.0.1:6379> get key2
"abcd123456"
127.0.0.1:6379> setrange key2 1 xx # 替换值
(integer) 10
127.0.0.1:6379> get key2
"axxd123456"
# setex 键 时间 expire
# setnx(set if not exist)
127.0.0.1:6379> setex key3 60 expire # 设置过期时间
OK
127.0.0.1:6379> ttl key3 # 查看剩余的时间
(integer) 55
127.0.0.1:6379> setnx mykey "redis" # 如果不存在就设置,成功返回1
(integer) 1
127.0.0.1:6379> setnx mykey "mongodb" # 如果存在就设置,失败返回0
(integer) 0
127.0.0.1:6379> get mykey
"redis"
# mset mset 命令用于同时设置一个或多个 key-value 键值对
# mget Mget 命令返回所有(一个或多个)给定 key 的值
# 如果给定的 key 里面,有某个 key 不存在,那么这个 key 返回特殊值 nil
# msetnx 当所有 key 都成功设置,返回 1
# 如果所有给定 key 都设置失败(至少有一个 key 已经存在),那么返回 0;原子操作
127.0.0.1:6379> mset k10 v10 k11 v11 k12 v12
OK
127.0.0.1:6379> keys *
1) "k12"
2) "k11"
3) "k10"
127.0.0.1:6379> mget k10 k11 k12 k13
1) "v10"
2) "v11"
3) "v12"
4) (nil)
127.0.0.1:6379> msetnx k10 v10 k15 v15 # 原子性操作!
(integer) 0
127.0.0.1:6379> get key15
(nil)
# 传统对象缓存
set user:1 value(json数据)
# 可以用来缓存对象
mset user:1:name zhangsan user:1:age 2
mget user:1:name user:1:age
# getset(先get再set)
127.0.0.1:6379> getset db mongodb # 没有旧值,返回 nil
(nil)
127.0.0.1:6379> get db
"mongodb"
127.0.0.1:6379> getset db redis # 返回旧值 mongodb
"mongodb"
127.0.0.1:6379> get db
"redis"
2.3. 列表 List
基本的数据类型,单值多value;redis 列表是简单的字符串列表,按照插入顺序排序,你可以添加一个元素到列表的头部或者尾部;底层实际是个链表;redis不区分大小写命令
# lpush:将一个或多个值插入到列表头部。(左)
# rpush:将一个或多个值插入到列表尾部。(右)
# lrange:返回列表中指定区间内的元素,区间以偏移量 START 和 END 指定
# 其中 0 表示列表的第一个元素, 1 表示列表的第二个元素,以此类推
# 也可以使用负数下标,以 -1 表示列表的最后一个元素, -2 表示列表的倒数第二个元素,以此类推
127.0.0.1:6379> LPUSH list "one"
(integer) 1
127.0.0.1:6379> LPUSH list "two"
(integer) 2
127.0.0.1:6379> RPUSH list "right"
(integer) 3
127.0.0.1:6379> Lrange list 0 -1
1) "two"
2) "one"
3) "right"
127.0.0.1:6379> Lrange list 0 1
1) "two"
2) "one"
# lpop 命令用于移除并返回列表的第一个元素。当列表 key 不存在时,返回 nil
# rpop 移除列表的最后一个元素,返回值为移除的元素
127.0.0.1:6379> lpop list
"two"
127.0.0.1:6379> rpop list
"right"
127.0.0.1:6379> lrange list 0 -1
1) "one"
# lindex,按照索引下标获得元素(-1代表最后一个,0代表是第一个)
127.0.0.1:6379> lindex list 1
(nil)
127.0.0.1:6379> lindex list 0
"one"
127.0.0.1:6379> lindex list -1
"one"
# llen 用于返回列表的长度
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> Lpush list "one"
(integer) 1
127.0.0.1:6379> Lpush list "two"
(integer) 2
127.0.0.1:6379> Lpush list "three"
(integer) 3
127.0.0.1:6379> Llen list # 返回列表的长度
(integer) 3
# lrem key 根据参数 COUNT 的值,移除列表中与参数 VALUE 相等的元素
127.0.0.1:6379> lrem list 1 "two"
(integer) 1
127.0.0.1:6379> Lrange list 0 -1
1) "three"
2) "one"
# Ltrim key 对一个列表进行修剪(trim),就是说,让列表只保留指定区间内的元素,
# 不在指定区间之内的元素都将被删除
127.0.0.1:6379> RPUSH mylist "hello"
(integer) 1
127.0.0.1:6379> RPUSH mylist "hello"
(integer) 2
127.0.0.1:6379> RPUSH mylist "hello2"
(integer) 3
127.0.0.1:6379> RPUSH mylist "hello3"
(integer) 4
127.0.0.1:6379> ltrim mylist 1 2
OK
127.0.0.1:6379> lrange mylist 0 -1
1) "hello"
2) "hello2"
# rpoplpush 移除列表的最后一个元素,并将该元素添加到另一个列表并返回。
127.0.0.1:6379> rpush mylist "hello"
(integer) 1
127.0.0.1:6379> rpush mylist "foo"
(integer) 2
127.0.0.1:6379> rpush mylist "bar"
(integer) 3
127.0.0.1:6379> rpoplpush mylist myotherlist
"bar"
127.0.0.1:6379> lrange mylist 0 -1
1) "hello"
2) "foo"
127.0.0.1:6379> lrange myotherlist 0 -1
1) "bar"
# lset key index value 将列表 key 下标为 index 的元素的值设置为 value 。
127.0.0.1:6379> exists list # 对空列表(key 不存在)进行 LSET
(integer) 0
127.0.0.1:6379> lset list 0 item # 报错
(error) ERR no such key
127.0.0.1:6379> lpush list "value1" # 对非空列表进行 LSET
(integer) 1
127.0.0.1:6379> lrange list 0 0
1) "value1"
127.0.0.1:6379> lset list 0 "new" # 更新值
OK
127.0.0.1:6379> lrange list 0 0
1) "new"
127.0.0.1:6379> lset list 1 "new" # index 超出范围报错
(error) ERR index out of range
# ===================================================
# linsert key before/after pivot value 用于在列表的元素前或者后插入元素。
# 将值 value 插入到列表 key 当中,位于值 pivot 之前或之后。
# ===================================================
redis> RPUSH mylist "Hello"
(integer) 1
redis> RPUSH mylist "World"
(integer) 2
redis> LINSERT mylist BEFORE "World" "There"
(integer) 3
redis> LRANGE mylist 0 -1
1) "Hello"
2) "There"
3) "World"
性能总结:
- 字符串链表,left,right 都可以插入添加
- 如果键不存在,创建新的链表
- 如果键已存在,新增内容
- 如果值全部移除,对应的键也就消失了
- 链表的操作无论是头和尾效率都极高,但假如是对中间元素进行操作,效率低
- 每个子元素都是String类型的双向链表,可以通过push和pop操作从列表的头部或者尾部添加或者删除元素,这样 list 即可以作为栈,也可以作为队列
2.4. 集合 Set
String 类型的无序集合,它是通过HashTable实现的
# sadd 将一个或多个成员元素加入到集合中,不能重复
# smembers 返回集合中的所有的成员
# sismember 命令判断成员元素是否是集合的成员
127.0.0.1:6379> sadd myset "hello"
(integer) 1
127.0.0.1:6379> sadd myset "kuangshen"
(integer) 1
127.0.0.1:6379> sadd myset "kuangshen"
(integer) 0
127.0.0.1:6379> smembers myset
1) "kuangshen"
2) "hello"
127.0.0.1:6379> sismember myset "hello"
(integer) 1
127.0.0.1:6379> sismember myset "world"
(integer) 0
# scard,获取集合里面的元素个数
127.0.0.1:6379> scard myset
(integer) 2
# srem key value 用于移除集合中的一个或多个成员元素
127.0.0.1:6379> srem myset "kuangshen"
(integer) 1
127.0.0.1:6379> smembers myset
1) "hello"
# srandmember key 命令用于返回集合中的一个随机元素。
127.0.0.1:6379> smembers myset
1) "kuangshen"
2) "world"
3) "hello"
127.0.0.1:6379> srandmember myset
"hello"
127.0.0.1:6379> srandmember myset 2
1) "world"
2) "kuangshen"
# spop key 用于移除集合中的指定 key 的一个或多个随机元素
127.0.0.1:6379> SMEMBERS myset
1) "kuangshen"
2) "world"
3) "hello"
127.0.0.1:6379> spop myset
"world"
127.0.0.1:6379> spop myset
"kuangshen"
127.0.0.1:6379> spop myset
"hello"
# smove SOURCE DESTINATION MEMBER
# 将指定成员 member 元素从 source 集合移动到 destination 集合
127.0.0.1:6379> sadd myset "hello"
(integer) 1
127.0.0.1:6379> sadd myset "world"
(integer) 1
127.0.0.1:6379> sadd myset "kuangshen"
(integer) 1
127.0.0.1:6379> sadd myset2 "set2"
(integer) 1
127.0.0.1:6379> smove myset myset2 "kuangshen"
(integer) 1
127.0.0.1:6379> SMEMBERS myset
1) "world"
2) "hello"
127.0.0.1:6379> SMEMBERS myset2
1) "kuangshen"
2) "set2"
# 数字集合类
# 差集: sdiff
# 交集: sinter
# 并集: sunion
127.0.0.1:6379> sadd key1 "a"
(integer) 1
127.0.0.1:6379> sadd key1 "b"
(integer) 1
127.0.0.1:6379> sadd key1 "c"
(integer) 1
127.0.0.1:6379> sadd key2 "c"
(integer) 1
127.0.0.1:6379> sadd key2 "d"
(integer) 1
127.0.0.1:6379> sadd key2 "e"
(integer) 1
127.0.0.1:6379> sdiff key1 key2 # 差集
1) "a"
2) "b"
127.0.0.1:6379> sinter key1 key2 # 交集
1) "c"
127.0.0.1:6379> sunion key1 key2 # 并集
1) "a"
2) "b"
3) "c"
4) "e"
5) "d"
2.5. 哈希 Hash---K-V模式不变,但V是键值对
Redis Hash是String类型的 field 和 value 的映射表,hash特别适合用于存储对象;Java里面的Map<String,Object>
# hset、hget 命令用于为哈希表中的字段赋值
# hmset、hmget 同时将多个field-value对设置到哈希表中。会覆盖哈希表中已存在的字段
# hgetall 用于返回哈希表中,所有的字段和值
# hdel 用于删除哈希表 key 中的一个或多个指定字段
127.0.0.1:6379> hset myhash field1 "kuangshen"
(integer) 1
127.0.0.1:6379> hget myhash field1
"kuangshen"
127.0.0.1:6379> hmset myhash field1 "Hello" field2 "World"
OK
127.0.0.1:6379> hget myhash field1
"Hello"
127.0.0.1:6379> hget myhash field2
"World"
127.0.0.1:6379> hgetall myhash
1) "field1"
2) "Hello"
3) "field2"
4) "World"
127.0.0.1:6379> hdel myhash field1
(integer) 1
127.0.0.1:6379> hgetall myhash
1) "field2"
2) "World"
# hlen 获取哈希表中字段的数量
127.0.0.1:6379> hlen myhash
(integer) 1
127.0.0.1:6379> hmset myhash field1 "Hello" field2 "World"
OK
127.0.0.1:6379> hlen myhash
(integer) 2
# hexists 查看哈希表的指定字段是否存在
127.0.0.1:6379> hexists myhash field1
(integer) 1
# hkeys 获取哈希表中的所有域(field)
# hvals 返回哈希表所有域(field)的值
127.0.0.1:6379> hkeys myhash
1) "field2"
2) "field1"
127.0.0.1:6379> hvals myhash
1) "World"
2) "Hello"
# hincrby 为哈希表中的字段值加上指定增量值
127.0.0.1:6379> hset myhash field 5
(integer) 1
127.0.0.1:6379> hincrby myhash field 1
(integer) 6
# hsetnx 为哈希表中不存在的的字段赋值
127.0.0.1:6379> hsetnx myhash field1 "hello"
(integer) 1 # 设置成功,返回 1
127.0.0.1:6379> hsetnx myhash field1 "world"
(integer) 0 # 如果给定字段已经存在,返回 0
2.6. 有序集合 ZSet
String类型元素的集合,且不允许重复的成员;与set不同的是每个元素都会关联一个double类型的分数,通过分数来为集合中的成员进行从小到大的排序,zset的成员是唯一的,但是分数却可以重复
和set相比,ZSet 增加了一个权重参数 score,使得集合中的元素能够按 score 进行有序排列
使用场景:set 排序存储班级成绩,工资排序,重要消息带权重进行判断
# zadd 将一个或多个成员元素及其分数值加入到有序集当中
# zrange 返回有序集中,指定区间内的成员
127.0.0.1:6379> zadd myset 1 "one"
(integer) 1
127.0.0.1:6379> zadd myset 2 "two" 3 "three"
(integer) 2
127.0.0.1:6379> zrange myset 0 -1
1) "one"
2) "two"
3) "three"
# zrangebyscore 返回有序集合中指定分数区间的成员列表; 有序集成员按分数值递增(从小到大)次序排列
# zrevrank 返回有序集中成员的排名; 其中有序集成员按分数值递减(从大到小)排序
127.0.0.1:6379> zadd salary 2500 xiaoming
(integer) 1
127.0.0.1:6379> zadd salary 5000 xiaohong
(integer) 1
127.0.0.1:6379> zadd salary 500 kuangshen
(integer) 1
# Inf无穷大量+∞,同样地,-∞可以表示为-Inf
127.0.0.1:6379> zrangebyscore salary -inf +inf # 显示整个有序集
1) "kuangshen"
2) "xiaoming"
3) "xiaohong"
127.0.0.1:6379> zrangebyscore salary -inf +inf withscores # 递增排列
1) "kuangshen"
2) "500"
3) "xiaoming"
4) "2500"
5) "xiaohong"
6) "5000"
127.0.0.1:6379> zrangebyscore salary -inf 2500 withscores # 显示工资 <=2500 的所有成员
1) "kuangshen"
2) "500"
3) "xiaoming"
4) "2500"
# zrevrank 返回有序集中成员的排名; 其中有序集成员按分数值递减(从大到小)排序
127.0.0.1:6379> zrevrange salary 0 -1 withscores # 递减排列
1) "xiaohong"
2) "5000"
3) "xiaoming"
4) "2500"
5) "kuangshen"
6) "500"
# zrem 移除有序集中的一个或多个成员
127.0.0.1:6379> zrange salary 0 -1
1) "kuangshen"
2) "xiaoming"
3) "xiaohong"
127.0.0.1:6379> zrem salary kuangshen
(integer) 1
127.0.0.1:6379> zrange salary 0 -1
1) "xiaoming"
2) "xiaohong"
# zcard 命令用于计算集合中元素的数量
127.0.0.1:6379> zcard salary
(integer) 2
OK
# zcount 计算有序集合中指定分数区间的成员数量
127.0.0.1:6379> zadd myset 1 "hello"
(integer) 1
127.0.0.1:6379> zadd myset 2 "world" 3 "kuangshen"
(integer) 2
127.0.0.1:6379> zcount myset 1 3
(integer) 3
127.0.0.1:6379> zcount myset 1 2
(integer) 2
# zrank 返回有序集中指定成员的排名。其中有序集成员按分数值递增(从小到大)顺序排列
127.0.0.1:6379> zadd salary 2500 xiaoming
(integer) 1
127.0.0.1:6379> zadd salary 5000 xiaohong
(integer) 1
127.0.0.1:6379> zadd salary 500 kuangshen
(integer) 1
127.0.0.1:6379> zrank salary 0 -1 WITHSCORES # 显示所有成员及其 score 值
1) "kuangshen"
2) "500"
3) "xiaoming"
4) "2500"
5) "xiaohong"
6) "5000"
127.0.0.1:6379> zrank salary kuangshen # 显示 kuangshen 的薪水排名,最少
(integer) 0
127.0.0.1:6379> zrank salary xiaohong # 显示 xiaohong 的薪水排名,第三
(integer) 2
# zrevrank 返回有序集中成员的排名。其中有序集成员按分数值递减(从大到小)排序
127.0.0.1:6379> zrevrank salary kuangshen # 狂神第三
(integer) 2
127.0.0.1:6379> zrevrank salary xiaohong # 小红第一
(integer) 0
3. 三种特殊数据类型(不重要)
3.1. geospatial 地理位置
地理位置经纬度坐标查询:https://www.toolnb.com/tools/gps.html
常用命令:
- geoadd key longitude latitude member
将给定的空间元素(纬度、经度、名字)添加到指定的键,这些数据会以有序集合的形式被储存在键里面;geoadd 命令以标准的x,y格式接受参数,所以用户必须先输入经度,然后再输入纬度
geoadd 能够记录的坐标是有限的,非常接近两极的区域无法被索引,有效的经度介于-180 ~ 180 度之间,有效的纬度介于 -85.05112878 度至 85.05112878 度之间;用户尝试输入一个超出范围的经度或者纬度时,geoadd命令将返回一个错误
127.0.0.1:6379> geoadd china:city 116.23 40.22 北京
(integer) 1
127.0.0.1:6379> geoadd china:city 121.48 31.40 上海 113.88 22.55 深圳 120.21
30.20 杭州
(integer) 3
127.0.0.1:6379> geoadd china:city 106.54 29.40 重庆 108.93 34.23 西安 114.02
30.58 武汉
(integer) 3
- geopos key member [member...]:从key里返回所有给定位置元素的位置
127.0.0.1:6379> geopos china:city 北京
1) 1) "116.23000055551528931"
2) "40.2200010338739844"
127.0.0.1:6379> geopos china:city 上海 重庆
1) 1) "121.48000091314315796"
2) "31.40000025319353938"
2) 1) "106.54000014066696167"
2) "29.39999880018641676"
127.0.0.1:6379> geopos china:city 新疆
1) (nil)
- geodist key member1 member2 [unit]:返回两个给定位置之间的距离;如果两个位置之间的其中一个不存在, 那么命令返回空值;指定单位的参数 unit 必须是以下单位的其中一个:m是米,km是公里,mi 是英里;ft 是英尺;
如果用户没有显式地指定单位参数,那么geodist默认使用米作为单位
127.0.0.1:6379> geodist china:city 北京 上海
"1088785.4302"
127.0.0.1:6379> geodist china:city 北京 上海 km
"1088.7854"
127.0.0.1:6379> geodist china:city 重庆 北京 km
"1491.6716"
- georadius key longitude latitude radius m|km|ft|mi [withcoord][withdist] [withhash][asc|desc][count count]:以给定的经纬度为中心, 找出某一半径内的元素
127.0.0.1:6379> GEORADIUSBYMEMBER china:city 北京 1000 km
北京
西安
127.0.0.1:6379> GEORADIUSBYMEMBER china:city 上海 400 km
杭州
上海
- zrem:zrem命令实现对地理位置信息的删除
127.0.0.1:6379> geoadd china:city 116.23 40.22 beijin
1
127.0.0.1:6379> zrange china:city 0 -1 # 查看全部的元素
重庆
西安
深圳
武汉
杭州
上海
beijin
北京
127.0.0.1:6379> zrem china:city beijin # 移除元素
1
127.0.0.1:6379> zrem china:city 北京 # 移除元素
1
127.0.0.1:6379> zrange china:city 0 -1
重庆
西安
深圳
武汉
杭州
上海
3.2. Hyperlog 基数统计
Redis 的 HyperLogLog 是用来做基数统计的算法;
优点:在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定的、并且是很小的
什么是基数:
数据集 {1, 3, 5, 7, 5, 7, 8}, 那么这个数据集的基数集为 {1, 3, 5 ,7, 8},基数(不重复元素)为5
127.0.0.1:6379> pfadd mykey a b c d e f g h i j
1
127.0.0.1:6379> pfcount mykey
10
127.0.0.1:6379> pfadd mykey2 i j z x c v b n m
1
127.0.0.1:6379> pfmerge mykey3 mykey mykey2
OK
127.0.0.1:6379> pfcount mykey3
15
3.3. Bitmap 位图场景
BitMap 就是通过一个 bit 位来表示某个元素对应的值或者状态, 其中的 key 就是对应元素本身,实际上底层也是通过对字符串的操作来实现
- setbit 存值
- getbit 取值
- bitcount 查询