Redis 是一个开源的内存数据结构存储系统,可用作数据库、缓存、消息代理和队列。Redis 以其出色的性能和可靠性闻名,因此被广泛应用于许多领域,如游戏、金融科技、广告科技、社交媒体、医疗保健和互联网等等。本文试图对 Redis 作简单的介绍,以便初学者快速上手 Redis。本文作为我的一篇学习笔记。
发布订阅模式
Redis 提供了发布订阅的功能,可以通过 PUBLISH 命令来将消息发送到指定的频道,然后通过 SUBSCRIBE 命令来订阅这个频道。
用法:PUBLISH channel message 将消息 message 发布到名为 channel 的频道。
用法:SUBSCRIBE channel [channel ...] 监听名为 channel 的频道,可以同时监听多个频道。
Redis 的发布订阅模式提供了简单的消息传输机制,但它仍然存在部分缺陷,譬如消息无法持久化、无法记录历史消息等等。
高级数据结构
Redis 支持五种高级数据类型,包括消息队列 Stream、地理空间 Geospatial、HyperLogLog、位图 Bitmap、位域 Bitfield。
消息队列
Stream 是 Redis 5.0 版本中引入的一个新的数据结构,它是一个轻量级的消息队列,可以用来解决发布订阅功能的部分局限性,譬如消息无法持久化、无法记录历史消息等等。Stream 相关的命令都以 X 开头。
用法:XADD key *|id field value 向键 key 指向的消息队列添加一个键为 field 值为 value 的消息,它的 id 可以由 id 字段指定,也可以指定 * 让 Redis 自动生成。
用法:XLEN key 查看 key 所指的消息队列的长度。
用法:XRANGE key start end 查看 key 所指的消息队列从 start 到 end 之间的所有消息,可以使用负数索引
用法:XDEL key id [id ...] 删除 key 所指的消息队列中的指定 id 的消息,可以指定多个 id。
用法:XTRIM key MAXLEN | MINID threshold MAXLEN 0 表示删除所有的消息,会返回删除的消息数量。
用法:XREAD [COUNT count] [BLOCK milliseconds] key 用于读取队列中的消息,COUNT 表示读取的个数,BLOCK 表示没有消息可读取时的阻塞时长,key 是消息队列的键。
用法:XGROUP CREATE key group id 创建一个消息的消费者组,key 指向消息队列,group 是组名。
用法:XINFO GROUPS key 查看消费者组的信息。
用法:XGROUP CREATECONSUMER key group member [member ...] 向消费者组添加消费者。
用法:XGROUP GROUP group member COUNT cnt BLOCK blk STREAMS key 以消费者组的组员身份读取消息队列中的消息。
地理空间
Geospatial 是 Redis3.2 版本中的新特性,它提供了一种存储地理位置信息的数据结构,同时支持对地理位置进行各种计算操作,比如计算两个位置之间的距离或者某个地理位置的经纬度,查找附近的人等等。地理位置相关的命令都以 GEO 开头。
用法:GEOADD key longitude latitude member key 指向一个地理空间的数据结构,longtitude 和 latitude 分别指向经度和纬度,可以输入浮点数,member 是在这个地理空间中的某个地点,也即经纬度所指。
用法:GEOPOS key member 获取 key 所指的地理空间中成员 member 的经纬度。他会返回一个数组,第一个表示经度,第二个表示纬度。
用法:GEODIST key member1 member2 获取 key 所指的地理空间中 member1 和 member2 之间的直线距离,默认单位为 M。
用法:GEOSEARCH key FROMMBER member BYRADIUS radius 查找 key 所指的地理空间中以成员 member 为起始点,圆形半径 radius 以内的其他成员。
HyperLogLog
HyperLogLog 是一种用来做基数统计的算法。注意:它并不是 Redis 特有的算法。
什么是基数呢? 如果集合中的每个元素都是唯一且不重复的,那么这个集合的基数就是集合中元素的个数。比如集合 {1, 2, 3, 4, 5} 的基数就是 5,而集合 {1, 2, 2, 3, 3, 3, 4, 4, 4, 5} 的基数仍然是 5。
HyperLogLog 算法就是用来计算这个基数的。它的原理是使用随机算法来计算,通过牺牲一定的精确度,来换取更小的内存消耗。HyperLogLog 的优点是占用内存小,相应的缺点是会有一定的误差,所以它适合用来做一些对精确度要求不高而且数据量非常大的统计工作,比如统计某个网站的 UV,统计某个词语的搜索次数等等。
在 Redis 中,HyperLogLog 相关的命令都以 PF 开头。
用法:PFADD key [element [element ...]] 向 key 指向的集合中添加 element,可以一次性添加多个 element。
用法:PFCOUNT key 查看 key 所指向的集合的基数。
用法:PFMERGE key1 key2 合并 key1 和 key2 所指向的两个集合。注意:这不是集合的并集操作,key1 和 key2 并非严格定义的数学集合,其中的元素都是可以重复的。
位图 Bitmap
位图是字符串类型的扩展。可以使用一个 String 类型来模拟一个 Bit 数组:数组的下标就是偏移量,值只有 0 和 1,也支持一些位运算比如与、或、非、亦或等等。他们的应用场景非常广泛,比如可以用来记录用户的签到情况、在线状态、有没有点过赞等。位图的所有命令都有 BIT。
用法:SETBIT key offset value 设置一个 key 指向的位图,他在偏移量为 offset 的值为 value,value 只能是 0 或者 1。
用法:GETBIT key offset 获取 key 指向的位图在偏移量为 offset 的值,返回 0 或者 1。
用法:BITCOUNT key 统计 key 指向的的位图中有多少位置为 1。
用法:BITPOS key 0|1 start end 获取 key 指向的位图中在 start 到 end 范围内第一个出现 0 或者 1 的位置。
位域 Bitfield
位域能够将很多小的整数存储到一个较大的位图中,这样就可以更加高效地使用内存。以游戏为例,可以使用位域来记录每个玩家在游戏中的一些关键信息,比如每个用户的金钱、等级、是否在线等等。这个时候你作为 1 号玩家进入了游戏,你刚刚出生在新手村,等级是 1 级,兜里有 100 个金币,那么就可以使用 BITFIELD 命令来设置一下。
用法:BITFIELD player:1 set u8 #0 1 表示为 player:1 设置了一个 u8 类型(8 位无符号整数)的整数,并将其放在第一个位置 #0 并制定了值为 1。在这之后使用 GET player:1 将返回 "\x01" 表示十六进制的 01。
用法:BITFIELD player:1 get u8 #0 表示获取 player:1 的 #0 号位置的数,它是 u8 类型,如果不指定正确的类型,可能会获得错误的结果。
事实上可以看到,位域的使用就是加快了内存的读取速度。事实上它是比较偏底层的,读写速度几乎和汇编语言差不多。