搜 索

Redis丨特殊数据类型

  • 187阅读
  • 2022年01月11日
  • 0评论
首页 / 默认分类 / 正文

前言

毕竟是干开发的,总不可能只在 Windows 环境运行 Redis 吧,对于在 Linux 环境下部署并使用也需要熟悉啊。

Linux 环境搭建

我的服务器版本:CentOS 7.9 64位,Redis 版本:Stable (6.2)

下载与安装

我使用的 SSH 客户端工具是:Github - electermTermius 太贵了,用不起啊。
打开官网的下载页,往下找,可以看到有说明下载、安装、编译的命令:

$ wget https://download.redis.io/releases/redis-6.2.6.tar.gz
$ tar xzf redis-6.2.6.tar.gz
$ cd redis-6.2.6
$ make

打开 electerm 登录 Linux,默认当前是根目录 /root,在 /root 目录下新建一个 opt 文件夹(额外安装的可选应用程序包所放置的位置),把下载的压缩文件使用 mv 命令移动过去,然后在 opt 目录下执行解压、编译命令:

# 默认下载到 /root 目录下
> wget https://download.redis.io/releases/redis-6.2.6.tar.gz
# 移动进 /root/opt/
> mv redis-6.2.6.tar.gz /opt
# 进入 opt 目录,执行解压
> tar xzf redis-6.2.6.tar.gz
# 进入
> cd redis-6.2.6
# 安装
> cd src && make install

如果不指定安装路径,默认安装到 /usr/local/bin,由于 /usr/local/bin 默认是在环境变量 PATH 中的,所以安装后就无需在解压后的 redis 源码目录中执行相关命令了,可以在任何地方执行,比较方便。当然,如果不想安装到默认路径 /usr/local/bin,可以通过 PREFIX 选项指定其他路径:

> make PREFIX=/some/other/directory install

配置与测试

Redis 可以多端口方式启动多个进程,会有多个配置文件,我在 /usr/local/bin 下新建一个配置文件目录 myconfig

> mkdir /usr/local/bin/myconfig

然后把将 Redis 原有的配置文件复制到目录 myconfig 下:

> cp /opt/redis-6.2.6/redis.conf /usr/local/bin/myconfig/redis.conf

开始编辑这个复制过来的配置文件,例如:启用守护进程方式运行、修改运行端口、允许外网可以连接 Redis 服务、修改日志级别、新增连接密码等。

> vim /usr/local/bin/myconfig/redis.conf

修改相关配置完毕后,在 /usr/local/bin 目录中,启动 Redis 服务端运行:

> redis-server myconfig/redis.conf

设置连接密码后,如果出现以下情况(没输入密码登录),说明设置生效了。

[root@VM-20-15-centos bin]# redis-cli -p 6379
127.0.0.1:6379> ping
(error) NOAUTH Authentication required.

# 再次输入密码验证
127.0.0.1:6379> auth ******
OK
127.0.0.1:6379> 

Redis 客户端源码包含一个名为 redis-benchmark 的性能测试工具,它可以模拟 N 个客户端同时向 Redis 发送 M 条查询命令的应用场景。redis-benchmark 工具的使用方法如下所示:

redis-benchmark [-h {ip}] [-p {port}] [-c {clients}] [-n {requests}]> [-k {boolean}]

测试:如下命令所示,使用 100 个并发连接、10W 个请求检测端口为 6379 的 Redis 服务器性能。

# 先启动服务
> redis-server myconfig/redis.conf
# 测试连接
> redis-cli -p 6379 auth ******
OK
# 测试性能
> redis-benchmark -h localhost -p 6379 -c 100 -n 100000
ERROR: NOAUTH Authentication required.
ERROR: failed to fetch CONFIG from localhost:6379

# 这是因为 redis 服务有设置密码,则通过 -a 参数指定为你的密码就可以
> redis-benchmark -h localhost -p 6379 -c 100 -n 100000 -a ******

3 种特殊类型

Bitmap

Bitmap 即位图,属于 string 数据类型,本质上是一个字节串,也就是 bytes 数组,通过操作二进制位来进行记录,只有 0 和 1 两个状态。

使用场景

例如:统计用户的信息,活跃与不活跃;已登录与未登录;已打卡与未打卡。凡是两种不同状态的,都可以使用 Bitmap。

SETBIT 命令

此命令用于设置 Bitmap 的值。语法格式如下:

> SETBIT key offset value
  • key :设置的别名。
  • offset:字节偏移量(二进制偏移量),如果 offset 过大,则会在中间填充 0,offset 最大到 232-1,即可推出最大的字符串为 512 M。
  • value:值(0 和 1),二进制中只有 0 和 1 两个数据。

测试:记录某用户 7 天的打卡签到情况,1 就是签到了,0 就是没有。

127.0.0.1:6379[0]> setbit bit1 0 1
0
127.0.0.1:6379[0]> setbit bit1 1 1
0
127.0.0.1:6379[0]> setbit bit1 2 0
0
127.0.0.1:6379[0]> setbit bit1 3 1
0
127.0.0.1:6379[0]> setbit bit1 4 0
0
127.0.0.1:6379[0]> setbit bit1 5 1
0
127.0.0.1:6379[0]> setbit bit1 6 1
0

GETBIT 命令

此命令用于返回 offset 处的二进制值。语法格式如下:

> GETBIT key offset
  • key :设置的别名。
  • offset:字节偏移量(二进制偏移量)。

测试:查看某用户一周内的某一天是否有打卡。

127.0.0.1:6379[0]> getbit bit1 5
1
127.0.0.1:6379[0]> getbit bit1 2
0
127.0.0.1:6379[0]> getbit bit1 4
0
127.0.0.1:6379[0]> getbit bit1 1
1

BITCOUNT 命令

此命令用于获取指定范围内值为 1 的个数。语法格式如下:

> BITCOUNT key [start end]
  • key:设置的别名。
  • start, end:二进制位的 offset 开始和结束的角标位。

返回在这些角标位中 1 的数量,如果 key 为时间,可以统计出这一天中有多少个用户在活跃,或者可以统计某个用户在一段时间内的活跃次数。
注意:Redis 的 setbit 命令设置或清除的是 bit 位置,而 bitcount 计算的是 byte 位置,1 byte = 8 bit。start 和 end 参数和 GETRANGE 命令的参数类似,都可以使用负数,比如 -1 表示倒数第一个位, -2 表示倒数第二个位。
测试:

127.0.0.1:6379[0]> bitcount bit1
6
更多命令查看官方文档:Redis - Bitmap

Geospatial

geospatial 即地理空间,将指定的地理空间位置(经度、纬度、名称)添加到指定的 key 中。主要用于存储地理位置信息,并对存储的信息进行操作,该功能在 Redis 3.2 版本新增。它的底层通过有序集合(ZSet)实现,不过它并没有与 ZSet 共用一套的命令,而是拥有自己的一套命令,它的命令都是以“GEO”为前缀。
注意:经度、纬度有范围限制,具体的限制由 EPSG:900913 / EPSG:3785 / OSGEO:41001 规定如下:

  • 有效的经度从 -180 度到 180 度。
  • 有效的纬度从 -85.05112878 度到 85.05112878 度。

地球上的北极点和南极点纬度都是 90 度,也就是说,北极、南极这两个极点也无法直接添加。

使用场景

这个可以推算地理位置的信息:两地之间的距离,附近的人(地址、信息)。所以有很多应用场景,例如:点外卖、打车、快递,在 APP 上会显示“店家距离你有多少米”、“司机师傅距离你有多远”、“快递员正在配送,距离你多少米”,类似这种功能就可以使用 Redis GEO 实现。

GEOADD 命令

geoadd 用于存储指定的地理空间位置,可以将一个或多个经度(longitude)、纬度(latitude)、位置名称(name)添加到指定的 key 中。语法格式如下:

> GEOADD key longitude latitude name [longitude latitude name ...]

可以在这个网站国内城市经度纬度在线查询工具获取城市的经纬度,搜索复制即可。
测试:

127.0.0.1:6379[0]> geoadd chinacity 117.190182 39.125596 天津市
1
127.0.0.1:6379[0]> geoadd chinacity 121.472644 31.231706 上海市 114.085947 22.547 深圳市
2
127.0.0.1:6379[0]> geoadd chinacity 113.382391,22.521113 中山市 113.552724 22.255899 珠海市
ERR syntax error. Try GEOADD key [x1] [y1] [name1] [x2] [y2] [name2] ... 
127.0.0.1:6379[0]> geoadd chinacity 113.382391 22.521113 中山市 113.552724 22.255899 珠海市
2
127.0.0.1:6379[0]> geoadd chinacity 108.948024 34.263161 西安市
1

注意,参数之间是空格隔开,别忘了检查一下复制过来的有逗号!!!返回值是 integer 类型的结果,表示添加到 geospatial 元素的数目,但不包括已更新的元素。

GEOPOS 命令

此命令用于从给定的 key 里返回所有指定名称(name)的位置(经度和纬度),不存在的返回 nil。语法格式如下:

> GEOPOS key name [name ...]

测试:

127.0.0.1:6379[0]> geopos chinacity 广州市 西安市
  113.28063815832138062
  23.12517743834835215
  108.94802302122116089
  34.2631604414749944
127.0.0.1:6379[0]> geopos chinacity 深圳市
  114.08594459295272827
  22.54699993773966327

GEODIST 命令

此命令用于返回两个给定位置之间的距离。如果两个位置之间的其中一个不存在, 那么命令返回空值。语法格式如下:

> GEODIST key name1 name2 [m|km|ft|mi]

name1、name2 为两个地理位置的名称。
指定单位的参数 unit 必须是以下单位的其中一个:

  • m 表示单位为米。
  • km 表示单位为千米。
  • mi 表示单位为英里。
  • ft 表示单位为英尺。

如果用户没有显式地指定单位参数, 那么 GEODIST 默认使用米作为单位。
测试:

127.0.0.1:6379[0]> geodist chinacity 深圳市 上海市
1211636.6370
127.0.0.1:6379[0]> geodist chinacity 中山市 上海市
1257176.8089
127.0.0.1:6379[0]> geodist chinacity 深圳市 西安市 km
1396.1268
127.0.0.1:6379[0]> geodist chinacity 天津市 上海市 km
960.1317

GEORADIUS 命令

以给定的经纬度为中心, 返回键包含的位置元素当中, 与中心的距离不超过给定最大距离的所有位置元素。语法格式如下:

> GEORADIUS key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC] [STORE key] [STOREDIST key]

参数说明:

  • m :米,默认单位。
  • km :千米。
  • mi :英里。
  • ft :英尺。
  • WITHDIST:在返回位置元素的同时, 将位置元素与中心之间的距离也一并返回。
  • WITHCOORD:将位置元素的经度和纬度也一并返回。
  • WITHHASH:以 52 位有符号整数的形式, 返回位置元素经过原始 geohash 编码的有序集合分值。这个选项主要用于底层应用或者调试, 实际中的作用并不大。
  • COUNT:限定返回的记录数。
  • ASC:查找结果根据距离从近到远排序。
  • DESC:查找结果根据从远到近排序。

在没有给定任何 WITH 选项的情况下, 命令只会返回一个像 [“New York”,”Milan”,”Paris”] 这样的线性(linear)列表。在指定了 WITHCOORDWITHDISTWITHHASH 等选项的情况下, 命令返回一个二层嵌套数组, 内层的每个子数组就表示一个元素。在返回嵌套数组时, 子数组的第一个元素总是位置元素的名字。 至于额外的信息, 则会作为子数组的后续元素, 按照以下顺序被返回:

  1. 以浮点数格式返回的中心与位置元素之间的距离, 单位与用户指定范围时的单位一致。
  2. geohash 整数。
  3. 由两个元素组成的坐标,分别为经度和纬度。

测试:

# 返回坐标 114 22 为中心 5000 km 为半径范围内的所有城市
127.0.0.1:6379[0]> georadius chinacity 114 22 5000 km
茂名市
西安市
珠海市
中山市
香港特别行政区
深圳市
广州市
东莞市
惠州市
上海市
天津市
# 半径 500 km,附带两者之间的中心距离
127.0.0.1:6379[0]> georadius chinacity 114 22 500 km withdist
  珠海市
  54.1658
  中山市
  86.0304
  香港特别行政区
  34.8112
  深圳市
  61.4805
  广州市
  145.3324
  东莞市
  119.2359
  惠州市
  127.3203
  茂名市
  320.3288
# 排序
127.0.0.1:6379[0]> georadius chinacity 114 22 500 km withdist asc
  香港特别行政区
  34.8112
  珠海市
  54.1658
  深圳市
  61.4805
  中山市
  86.0304
  东莞市
  119.2359
  惠州市
  127.3203
  广州市
  145.3324
  茂名市
  320.3288
# 限制返回数据的数量,返回三条
127.0.0.1:6379[0]> georadius chinacity 114 22 500 km withdist count 3
  香港特别行政区
  34.8112
  珠海市
  54.1658
  深圳市
  61.4805

GEORADIUSBYMEMBER 命令

这个命令和 GEORADIUS 命令一样, 都可以找出位于指定范围内的元素, 但是 GEORADIUSBYMEMBER 的中心点是由给定的位置元素决定的, 而不是像 GEORADIUS 那样, 使用输入的经度和纬度来决定中心点。语法格式如下:

> GEORADIUSBYMEMBER key member radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC] [STORE key] [STOREDIST key]

测试:

127.0.0.1:6379[0]> georadiusbymember chinacity 深圳市 500 km
珠海市
中山市
香港特别行政区
深圳市
广州市
东莞市
惠州市
茂名市

GEOHASH 命令

返回一个或多个位置元素的 Geohash 值,返回的 geohash 的位置与用户给定的位置元素的位置一一对应。将二维的经纬度转换为一维的字符串, 如果两个字符串越接近, 则距离越近。这个使用较少。语法格式如下:

> GEOHASH key name [name ...]

测试:

127.0.0.1:6379[0]> geohash chinacity 广州市 深圳市
ws0e9cb3yj0
ws10k0dcg10

删除命令

Note: there is no GEODEL command because you can use ZREM to remove elements. The Geo index structure is just a sorted set.

简单翻译一下,就是说没有 GEODEL 命令,因为可以使用 ZREM 删除元素,地理索引结构只是一个排序集。
GEO 的底层其实是 ZSet,所以可以使用 ZSet 的命令去操作 GEO。
测试:

127.0.0.1:6379[0]> zrange chinacity 0 -1
茂名市
西安市
珠海市
中山市
香港特别行政区
深圳市
广州市
东莞市
惠州市
上海市
天津市
127.0.0.1:6379[0]> zrem chinacity 西安市
1
127.0.0.1:6379[0]> zrange chinacity 0 -1
茂名市
珠海市
中山市
香港特别行政区
深圳市
广州市
东莞市
惠州市
上海市
天津市
更多命令查看官方文档:Redis - Geo

HyperLogLog

Redis 在 2.8.9 版本添加了 HyperLogLog 结构。HyperLogLog 是用来做基数统计的算法,优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定的并且是很小的。
那什么是基数?基数就是指一个集合中不同值的数目,比如 a, b, c, d 的基数就是 4,a, b, c, d, a 的基数还是 4。虽然 a 出现两次,只会被计算一次。

使用场景

这个结构可以非常省内存的去统计各种计数,比如注册 IP 数、每日访问 IP 数、页面实时UV、在线用户数(人气值),共同好友数等。但必须要允许一定的容错率,如果要求百分百准确的就不能用它,因为它存在一定的误差,误差率整体较低,标准误差为 0.81%

PFADD 命令

此命令将所有元素参数添加到 HyperLogLog 数据结构中。返回值是整型,如果至少有 1 个元素被添加返回 1, 否则返回 0。语法格式如下:

> PFADD key [element [element ...]]

测试:

127.0.0.1:6379[0]> pfadd loglog a b c d e f g h i j
1

PFCOUNT 命令

此命令返回给定 HyperLogLog 的基数估算值。返回值是整数,返回给定 HyperLogLog 的基数值,如果多个 HyperLogLog 则返回基数估值之和。语法格式如下:

> PFCOUNT key [key ...]

测试:

127.0.0.1:6379[0]> pfcount loglog
10
127.0.0.1:6379[0]> pfadd loglog2 top jun mid adc sup
1
127.0.0.1:6379[0]> pfcount loglog loglog2
15

PFMERGE 命令

此命令将多个 HyperLogLog 合并为一个 HyperLogLog ,合并后的 HyperLogLog 的基数估算值是通过对所有给定 HyperLogLog 进行并集计算得出的。返回值为 OK。语法格式如下:

> PFMERGE destkey sourcekey [sourcekey ...]

测试:

127.0.0.1:6379[0]> pfmerge finallog loglog loglog2
OK
更多命令查看官方文档:Redis - HyperLogLog

参考

Redis官方文档
Java 全栈知识体系 - Redis教程
打 赏
  • 支付宝
  • 微信
Alipay
WeChatPay
评论区
暂无评论
avatar