💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
> **Redis-常用类型操作命令 4(HyperLogLog/地理位置/位图)** [TOC] ## 说明 ## **记录以下Redis常用类型的操作命令。** ---------- ##HyperLogLog## <h5>简单介绍</h5> Redis 在 2.8.9 版本添加了 HyperLogLog 结构。 Redis HyperLogLog 是用来做基数统计的算法,HyperLogLog 的优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定 的、并且是很小的。 在 Redis 里面,每个 HyperLogLog 键只需要花费 12 KB 内存,就可以计算接近 2^64 个不同元素的基 数。这和计算基数时,元素越多耗费内存就越多的集合形成鲜明对比。 但是,因为 HyperLogLog 只会根据输入元素来计算基数,而不会储存输入元素本身,所以 HyperLogLog 不能像集合那样,返回输入的各个元素。 <h5>什么是基数?</h5> 比如数据集 {1, 3, 5, 7, 5, 7, 8}, 那么这个数据集的基数集为 {1, 3, 5 ,7, 8}, 基数(不重复元素)为5。 基数估计就是在误差可接受的范围内,快速计算基数 <h5>PFADD(增加元素)</h5> 将任意数量的元素添加到指定的 HyperLogLog 里面。 作为这个命令的副作用, HyperLogLog 内部可能会被更新, 以便反映一个不同的唯一元素估计数量(也即是集合的基数)。 如果 HyperLogLog 估计的近似基数(approximated cardinality)在命令执行之后出现了变化, 那么命令返回 1 , 否则返回 0 。 如果命令执行时给定的键不存在, 那么程序将先创建一个空的 HyperLogLog 结构, 然后再执行命令。 调用 PFADD key element [element …] 命令时可以只给定键名而不给定元素: 如果给定键已经是一个 HyperLogLog , 那么这种调用不会产生任何效果; 但如果给定的键不存在, 那么命令会创建一个空的 HyperLogLog , 并向客户端返回 1 。 要了解更多关于 HyperLogLog 数据结构的介绍知识, 请查阅 PFCOUNT key [key …] 命令的文档。 返回值:整数回复: 如果 HyperLogLog 的内部储存被修改了, 那么返回 1 , 否则返回 0 。 ---------- redis> PFADD databases "Redis" "MongoDB" "MySQL" (integer) 1 redis> PFCOUNT databases (integer) 3 redis> PFADD databases "Redis" # Redis 已经存在,不必对估计数量进行更新 (integer) 0 redis> PFCOUNT databases # 元素估计数量没有变化 (integer) 3 redis> PFADD databases "PostgreSQL" # 添加一个不存在的元素 (integer) 1 redis> PFCOUNT databases # 估计数量增一 4 <h5>PFCOUNT(返回近似基数)</h5> PFCOUNT key [key …] 时间复杂度: 当命令作用于单个 HyperLogLog 时, 复杂度为 O(1) , 并且具有非常低的平均常数时间。 当命令作用于 N 个 HyperLogLog 时, 复杂度为 O(N) , 常数时间也比处理单个 HyperLogLog 时要大得多。 当 PFCOUNT key [key …] 命令作用于单个键时, 返回储存在给定键的 HyperLogLog 的近似基数, 如果键不存在, 那么返回 0 。 当 PFCOUNT key [key …] 命令作用于多个键时, 返回所有给定 HyperLogLog 的并集的近似基数, 这个近似基数是通过将所有给定 HyperLogLog 合并至一个临时 HyperLogLog 来计算得出的。 通过 HyperLogLog 数据结构, 用户可以使用少量固定大小的内存, 来储存集合中的唯一元素 (每个 HyperLogLog 只需使用 12k 字节内存,以及几个字节的内存来储存键本身)。 命令返回的可见集合(observed set)基数并不是精确值, 而是一个带有 0.81% 标准错误(standard error)的近似值。 举个例子, 为了记录一天会执行多少次各不相同的搜索查询, 一个程序可以在每次执行搜索查询时调用一次 PFADD key element [element …] , 并通过调用 PFCOUNT key [key …] 命令来获取这个记录的近似结果。 返回值整数回复: 给定 HyperLogLog 包含的唯一元素的近似数量。 ---------- redis 127.0.0.1:6379> PFADD hll foo bar zap (integer) 1 redis 127.0.0.1:6379> PFADD hll zap zap zap (integer) 0 redis 127.0.0.1:6379> PFADD hll foo bar (integer) 0 redis 127.0.0.1:6379> PFCOUNT hll (integer) 3 redis 127.0.0.1:6379> PFADD some-other-hll 1 2 3 (integer) 1 redis 127.0.0.1:6379> PFCOUNT hll some-other-hll (integer) 6 redis> <h5>PFMERGE(合并HyperLogLog )</h5> 将多个 HyperLogLog 合并(merge)为一个 HyperLogLog , 合并后的 HyperLogLog 的基数接近于所有输入 HyperLogLog 的可见集合(observed set)的并集。 合并得出的 HyperLogLog 会被储存在 destkey 键里面, 如果该键并不存在, 那么命令在执行之前, 会先为该键创建一个空的 HyperLogLog 。 返回值字符串回复:返回 OK 。 ---------- redis> PFADD nosql "Redis" "MongoDB" "Memcached" (integer) 1 redis> PFADD RDBMS "MySQL" "MSSQL" "PostgreSQL" (integer) 1 redis> PFMERGE databases nosql RDBMS OK redis> PFCOUNT databases (integer) 6 ##地理位置## <h5>GEOADD(添加地理元素)</h5> 将给定的空间元素(纬度、经度、名字)添加到指定的键里面。 这些数据会以有序集合的形式被储存在键里面, 从而使得像 GEORADIUS 和 GEORADIUSBYMEMBER 这样的命令可以在之后通过位置查询取得这些元素。 GEOADD 命令以标准的 x,y 格式接受参数, 所以用户必须先输入经度, 然后再输入纬度。 GEOADD 能够记录的坐标是有限的: 非常接近两极的区域是无法被索引的。 精确的坐标限制由 EPSG:900913 / EPSG:3785 / OSGEO:41001 等坐标系统定义, 具体如下: 有效的经度介于 -180 度至 180 度之间。 有效的纬度介于 -85.05112878 度至 85.05112878 度之间。 用户尝试输入一个超出范围的经度或者纬度时, GEOADD 命令将返回一个错误。 返回值:新添加到键里面的空间元素数量, 不包括那些已经存在但是被更新的元素。 ---------- redis> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania" (integer) 2 redis> GEODIST Sicily Palermo Catania "166274.15156960039" redis> GEORADIUS Sicily 15 37 100 km 1) "Catania" redis> GEORADIUS Sicily 15 37 200 km 1) "Palermo" 2) "Catania" <h5>GEOPOS(获取元素)</h5> 从键里面返回所有给定位置元素的位置(经度和纬度)。 因为 GEOPOS 命令接受可变数量的位置元素作为输入, 所以即使用户只给定了一个位置元素, 命令也会返回数组回复。 返回值:GEOPOS 命令返回一个数组, 数组中的每个项都由两个元素组成: 第一个元素为给定位置元素的经度, 而第二个元素则为给定位置元素的纬度。 当给定的位置元素不存在时, 对应的数组项为空值。 ---------- redis> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania" (integer) 2 redis> GEOPOS Sicily Palermo Catania NonExisting 1) 1) "13.361389338970184" 2) "38.115556395496299" 2) 1) "15.087267458438873" 2) "37.50266842333162" 3) (nil) <h5>GEODIST(返回两个元素距离)</h5> GEODIST key member1 member2 [unit]:返回两个给定位置之间的距离。 如果两个位置之间的其中一个不存在, 那么命令返回空值。 指定单位的参数 unit 必须是以下单位的其中一个: m 表示单位为米。 km 表示单位为千米。 mi 表示单位为英里。 ft 表示单位为英尺。 如果用户没有显式地指定单位参数, 那么 GEODIST 默认使用米作为单位。 GEODIST 命令在计算距离时会假设地球为完美的球形, 在极限情况下, 这一假设最大会造成 0.5% 的误差。 返回值:计算出的距离会以双精度浮点数的形式被返回。 如果给定的位置元素不存在, 那么命令返回空值。 ---------- redis> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania" (integer) 2 redis> GEODIST Sicily Palermo Catania "166274.15156960039" redis> GEODIST Sicily Palermo Catania km "166.27415156960038" redis> GEODIST Sicily Palermo Catania mi "103.31822459492736" redis> GEODIST Sicily Foo Bar (nil) <h5>GEORADIUS(返回半径圆内的元素)</h5> GEORADIUS key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [ASC|DESC] [COUNT count] 以给定的经纬度为中心, 返回键包含的位置元素当中, 与中心的距离不超过给定最大距离的所有位置元素。 范围可以使用以下其中一个单位: m 表示单位为米。 km 表示单位为千米。 mi 表示单位为英里。 ft 表示单位为英尺。 在给定以下可选项时, 命令会返回额外的信息: WITHDIST : 在返回位置元素的同时, 将位置元素与中心之间的距离也一并返回。 距离的单位和用户给定的范围单位保持一致。 WITHCOORD : 将位置元素的经度和维度也一并返回。 WITHHASH : 以 52 位有符号整数的形式, 返回位置元素经过原始 geohash 编码的有序集合分值。 这个选项主要用于底层应用或者调试, 实际中的作用并不大。 命令默认返回未排序的位置元素。 通过以下两个参数, 用户可以指定被返回位置元素的排序方式: ASC : 根据中心的位置, 按照从近到远的方式返回位置元素。 DESC : 根据中心的位置, 按照从远到近的方式返回位置元素。 在默认情况下, GEORADIUS 命令会返回所有匹配的位置元素。 虽然用户可以使用 COUNT <count> 选项去获取前 N 个匹配元素, 但是因为命令在内部可能会需要对所有被匹配的元素进行处理, 所以在对一个非常大的区域进行搜索时, 即使只使用 COUNT 选项去获取少量元素, 命令的执行速度也可能会非常慢。 但是从另一方面来说, 使用 COUNT 选项去减少需要返回的元素数量, 对于减少带宽来说仍然是非常有用的。 ---------- **返回值** GEORADIUS 命令返回一个数组, 具体来说: 在没有给定任何 WITH 选项的情况下, 命令只会返回一个像 ["New York","Milan","Paris"] 这样的线性(linear)列表。 在指定了 WITHCOORD 、 WITHDIST 、 WITHHASH 等选项的情况下, 命令返回一个二层嵌套数组, 内层的每个子数组就表示一个元素。 在返回嵌套数组时, 子数组的第一个元素总是位置元素的名字。 至于额外的信息, 则会作为子数组的后续元素, 按照以下顺序被返回: 以浮点数格式返回的中心与位置元素之间的距离, 单位与用户指定范围时的单位一致。 geohash 整数。 由两个元素组成的坐标,分别为经度和纬度。 举个例子, GEORADIUS Sicily 15 37 200 km withcoord withdist 这样的命令返回的每个子数组都是类似以下格式的: ["Palermo","190.4424",["13.361389338970184","38.115556395496299"]] ---------- redis> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania" (integer) 2 redis> GEORADIUS Sicily 15 37 200 km WITHDIST 1) 1) "Palermo" 2) "190.4424" 2) 1) "Catania" 2) "56.4413" redis> GEORADIUS Sicily 15 37 200 km WITHCOORD 1) 1) "Palermo" 2) 1) "13.361389338970184" 2) "38.115556395496299" 2) 1) "Catania" 2) 1) "15.087267458438873" 2) "37.50266842333162" redis> GEORADIUS Sicily 15 37 200 km WITHDIST WITHCOORD 1) 1) "Palermo" 2) "190.4424" 3) 1) "13.361389338970184" 2) "38.115556395496299" 2) 1) "Catania" 2) "56.4413" 3) 1) "15.087267458438873" 2) "37.50266842333162" <h5>GEORADIUSBYMEMBER(返回半径圆内的元素)</h5> GEORADIUSBYMEMBER key member radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [ASC|DESC] [COUNT count] 这个命令和 GEORADIUS 命令一样, 都可以找出位于指定范围内的元素, 但是 GEORADIUSBYMEMBER 的中心点是由给定的位置元素决定的, 而不是像 GEORADIUS 那样, 使用输入的经度和纬度来决定中心点。 关于 GEORADIUSBYMEMBER 命令的更多信息, 请参考 GEORADIUS 命令的文档。 返回值:一个数组, 数组中的每个项表示一个范围之内的位置元素。 ---------- redis> GEOADD Sicily 13.583333 37.316667 "Agrigento" (integer) 1 redis> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania" (integer) 2 redis> GEORADIUSBYMEMBER Sicily Agrigento 100 km 1) "Agrigento" 2) "Palermo" <h5>GEOHASH(GEOHASH)</h5> GEOHASH key member [member …]返回一个或多个位置元素的 Geohash 表示。 返回值:一个数组, 数组的每个项都是一个 geohash 。 命令返回的 geohash 的位置与用户给定的位置元素的位置一一对应。 ---------- redis> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania" (integer) 2 redis> GEOHASH Sicily Palermo Catania 1) "sqc8b49rny0" 2) "sqdtr74hyu0" ##位图## 1个字节( b ) = 8位( bit ) = 0.001 千字节( kb ) <h5>SETBIT</h5> SETBIT key offset value 对 key 所储存的字符串值,设置或清除指定偏移量上的位(bit)。 位的设置或清除取决于 value 参数,可以是 0 也可以是 1 。 当 key 不存在时,自动生成一个新的字符串值。 字符串会进行伸展(grown)以确保它可以将 value 保存在指定的偏移量上。当字符串值进行伸展时,空白位置以 0 填充。 offset 参数必须大于或等于 0 ,小于 2^32 (bit 映射被限制在 512 MB 之内)。 ---------- Warning 对使用大的 offset 的 SETBIT 操作来说,内存分配可能造成 Redis 服务器被阻塞。具体参考 SETRANGE key offset value 命令,warning(警告)部分。 返回值:指定偏移量原来储存的位。 ---------- redis> SETBIT bit 10086 1 (integer) 0 redis> GETBIT bit 10086 (integer) 1 redis> GETBIT bit 100 # bit 默认被初始化为 0 (integer) 0 <h5>GETBIT</h5> GETBIT key offset:对 key 所储存的字符串值,获取指定偏移量上的位(bit)。 当 offset 比字符串值的长度大,或者 key 不存在时,返回 0 。 返回值:字符串值指定偏移量上的位(bit)。 ---------- > 对不存在的 key 或者不存在的 offset 进行 GETBIT, 返回 0 redis> EXISTS bit (integer) 0 redis> GETBIT bit 10086 (integer) 0 # 对已存在的 offset 进行 GETBIT redis> SETBIT bit 10086 1 (integer) 0 redis> GETBIT bit 10086 (integer) 1 <h5>BITCOUNT</h5> BITCOUNT key [start] [end]:计算给定字符串中,被设置为 1 的比特位的数量。 一般情况下,给定的整个字符串都会被进行计数,通过指定额外的 start 或 end 参数,可以让计数只在特定的位上进行。 start 和 end 参数的设置和 GETRANGE key start end 命令类似,都可以使用负数值: 比如 -1 表示最后一个字节, -2 表示倒数第二个字节,以此类推。 不存在的 key 被当成是空字符串来处理,因此对一个不存在的 key 进行 BITCOUNT 操作,结果为 0 。 返回值:被设置为 1 的位的数量。 ---------- redis> BITCOUNT bits (integer) 0 redis> SETBIT bits 0 1 # 0001 (integer) 0 redis> BITCOUNT bits (integer) 1 redis> SETBIT bits 3 1 # 1001 (integer) 0 redis> BITCOUNT bits (integer) 2 <h5>BITPOS</h5> BITPOS key bit [start] [end]:返回位图中第一个值为 bit 的二进制位的位置。 在默认情况下, 命令将检测整个位图, 但用户也可以通过可选的 start 参数和 end 参数指定要检测的范围。 返回值:整数回复。 ---------- 127.0.0.1:6379> SETBIT bits 3 1 # 1000 (integer) 0 127.0.0.1:6379> BITPOS bits 0 (integer) 0 127.0.0.1:6379> BITPOS bits 1 (integer) 3 <h5>BITOP</h5> BITOP operation destkey key [key …]:对一个或多个保存二进制位的字符串 key 进行位元操作,并将结果保存到 destkey 上。 operation 可以是 AND 、 OR 、 NOT 、 XOR 这四种操作中的任意一种: BITOP AND destkey key [key ...] ,对一个或多个 key 求逻辑并,并将结果保存到 destkey 。 BITOP OR destkey key [key ...] ,对一个或多个 key 求逻辑或,并将结果保存到 destkey 。 BITOP XOR destkey key [key ...] ,对一个或多个 key 求逻辑异或,并将结果保存到 destkey 。 BITOP NOT destkey key ,对给定 key 求逻辑非,并将结果保存到 destkey 。 除了 NOT 操作之外,其他操作都可以接受一个或多个 key 作为输入。 处理不同长度的字符串 当 BITOP 处理不同长度的字符串时,较短的那个字符串所缺少的部分会被看作 0 。 空的 key 也被看作是包含 0 的字符串序列。 返回值:保存到 destkey 的字符串的长度,和输入 key 中最长的字符串长度相等。 Note BITOP 的复杂度为 O(N) ,当处理大型矩阵(matrix)或者进行大数据量的统计时,最好将任务指派到附属节点(slave)进行,避免阻塞主节点。 ---------- redis> SETBIT bits-1 0 1 # bits-1 = 1001 (integer) 0 redis> SETBIT bits-1 3 1 (integer) 0 redis> SETBIT bits-2 0 1 # bits-2 = 1011 (integer) 0 redis> SETBIT bits-2 1 1 (integer) 0 redis> SETBIT bits-2 3 1 (integer) 0 redis> BITOP AND and-result bits-1 bits-2 (integer) 1 redis> GETBIT and-result 0 # and-result = 1001 (integer) 1 redis> GETBIT and-result 1 (integer) 0 redis> GETBIT and-result 2 (integer) 0 redis> GETBIT and-result 3 (integer) 1 ## 结尾 ## <p style="background-image: -webkit-linear-gradient(left, #3498db, #f47920 10%, #d71345 20%, #f7acbc 30%,#ffd400 40%, #3498db 50%, #f47920 60%, #d71345 70%, #f7acbc 80%, #ffd400 90%, #3498db);color: transparent;-webkit-text-fill-color: transparent;-webkit-background-clip: text;text-align:center;"> 腹有诗书气自华,最是书香能致远。 </p>