Redis是一个开源的,基于内存的数据结构存储系统,它可以用作数据库、缓存和消息中间件。
Redis支持多种类型的数据结构,包括:
字符串Strings是Redis最基本的数据类型,它是二进制安全的。一个Redis字符串可以包含任何类型的数据,比如jpg图片或者序列化的对象。一个字符串类型的值最大能存储512MB。
以下是String类型的常见命令和用法
SET mykey "Hello" -- 设置键值
GET mykey -- 获取键值
DEL mykey -- 删除键值
APPEND mykey " World" -- 追加值到现有的键值
SETEX mykey 10 "Hello" -- 设置键值,并设置键的过期时间(例如,10秒)
MSET key1 "Hello" key2 "World" -- 批量设置键值
MGET key1 key2 -- 批量获取键值
INCR mycounter -- 将键值递增1
DECR mycounter -- 将键值递减1
INCRBY mycounter 10 -- 将键值按给定数值递增(例如,递增10)
DECRBY mycounter 10 -- 将键值按给定数值递减(例如,递减10)
Redis的字符串类型的值是动态字符串SDS,可以修改的字符串长度。内部结构实现类似于Java的ArrayList,采用预分配冗余空间的方式来减少内存的频繁分配。当字符串长度小于1M时,扩容都是加倍现有的空间,如果超过1M,扩容时一次只会多分配1M的空间。需要注意的是字符串最大长度为512M。
字符串是最常用的数据类型,常见的使用场景有:
SDS是Redis的默认字符串表示,它是Redis的基础数据结构,用于构建更复杂的数据结构如列表、哈希表等。SDS相比于C语言的字符串,提供了更高的效率和灵活性。
SDS的数据结构包含三部分:
String的底层实现原理
在Redis中,String类型的值就是一个SDS。当我们对String进行操作时,实际上就是在对SDS进行操作。
Redis的List数据类型是一个由字符串组成的有序列表。列表中的每个字符串都被分配了一个新的索引,这个索引表示了这个字符串在列表中的位置。索引是零基的,这意味着第一个元素的索引是0,第二个元素的索引是1,以此类推。Redis的列表是双向的,这意味着你可以在列表的两端添加或删除元素。
以下是一些使用Redis列表(List)类型的示例代码:
LPUSH mylist "World"-- 在列表的左侧添加一个或多个值
RPUSH mylist "Hello"-- 在列表的右侧添加一个或多个值
LRANGE mylist 0 -1-- 获取列表中的所有元素
LINDEX mylist 0-- 获取列表中指定位置的元素
LPOP mylist-- 移除并返回列表的第一个元素
RPOP mylist-- 移除并返回列表的最后一个元素
LLEN mylist-- 返回列表的长度
Redis的List数据类型是通过双向链表实现的,这使得在列表的头部和尾部插入或删除元素的操作非常高效。然而,当你需要访问或者修改列表中间的元素时,性能就会下降,因为需要从头部或尾部开始遍历列表。
由于Redis的List数据类型提供了在列表两端进行操作的能力,因此它非常适合用于实现队列和栈,这两种数据结构在许多实际应用中都非常有用。
例如,你可以使用Redis的List数据类型来实现一个消息队列,其中生产者将消息添加到列表的一端,消费者则从另一端取出消息。
Redis的Set是字符串的无序集合。Set是通过哈希表实现的,所以添加、删除、查找的复杂度都是O(1)。Set中最大的成员数为 2^32 - 1 (大约40亿)。
以下是一些使用Redis集合(SET)类型的示例代码:
SADD myset "Hello"-- 向集合添加一个或多个成员
SREM myset "Hello"-- 移除集合中一个或多个成员
SISMEMBER myset "Hello"-- 判断成员元素是否是集合的成员
SMEMBERS myset-- 返回集合中的所有成员
SCARD myset-- 返回集合的成员数
SUNION set1 set2-- 返回两个集合的并集
SINTER set1 set2-- 返回两个集合的交集
SDIFF set1 set2-- 返回两个集合的差集
Redis的SET数据类型是通过哈希表实现的,这使得添加、删除和查找等操作的时间复杂度都是O(1)。这种数据结构的优点是操作速度快,但是缺点是占用的内存比较大。
Redis的Sorted SET是SET的升级版,它在SET的基础上增加了一个权重参数score,使得集合中的元素能够按score进行有序排列。在Sorted SET中,元素是唯一的,但score可以重复。
以下是一些使用Redis有序集合(Sorted SET)类型的示例代码:
ZADD myzset 1 "one"-- 向有序集合添加一个或多个成员,或者更新已存在成员的分数
ZSCORE myzset "one"-- 返回有序集中,成员的分数值
ZRANK myzset "one"-- 返回有序集合中指定成员的索引
ZRANGE myzset 0 -1-- 通过索引区间返回有序集合成指定区间内的成员
ZREM myzset "one"-- 移除有序集合中的一个或多个成员
ZCARD myzset-- 获取有序集合的成员数
ZCOUNT myzset min max-- 计算在有序集合中指定区间分数的成员数
Redis的Sorted SET数据类型是通过跳跃列表(Skip List)和哈希表(Hash Table)实现的。哈希表用于支持O(1)复杂度的元素查找,而跳跃列表则用于支持元素的有序排列和区间查找。
当我们向有序集合中添加一个元素时,Redis会同时向跳跃列表和哈希表中添加这个元素。其中,跳跃列表按照元素的score进行排序,而哈希表则按照元素的值进行映射。
当我们查询一个元素时,如果是按照score进行区间查询,Redis会使用跳跃列表;如果是按照元素的值进行查询,Redis会使用哈希表。
当我们删除一个元素时,Redis会同时从跳跃列表和哈希表中删除这个元素。
通过这种方式,Redis的有序集合既可以进行快速的插入和删除,也可以进行快速的排序和区间查询,从而满足了各种不同的需求。
Redis的哈希类型是一个由键值对组成的无序散列表。哈希类型适合用于存储对象,其中键名对应字段名,键值对应字段值。
以下是一些使用Redis哈希(Hash)类型的示例代码:
HSET myhash field1 "Hello"-- 设置哈希表中一个字段的值
HGET myhash field1-- 获取存储在哈希表中指定字段的值
HGETALL myhash-- 获取在哈希表中指定的所有字段和值
HDEL myhash field1-- 删除一个或多个哈希表字段
HEXISTS myhash field1-- 查看哈希表中,指定的字段是否存在
HLEN myhash-- 获取哈希表中字段的数量
HKEYS myhash-- 获取所有哈希表中的字段
HVALS myhash-- 获取哈希表中所有值
Redis的Hash数据类型是通过哈希表实现的,这使得添加、删除和查找等操作的时间复杂度都是O(1)。这种数据结构的优点是操作速度快,但是缺点是占用的内存比较大。
Redis并没有专门的Bitmap数据类型,但是它提供了一系列的位操作命令,使得我们可以把字符串当作Bitmap来使用。Bitmaps是一种特殊的数组,其中的每个元素只能存储0和1。例如,一个8位的Bitmap可以存储从0到255的整数。
以下是一些使用Redis Bitmaps的示例代码:
SETBIT mykey 7 1 -- 设置或清除指定偏移量上的位(bit)
GETBIT mykey 7 -- 获取指定偏移量上的位(bit)
BITCOUNT mykey -- 计算给定字符串中被设置为 1 的位的数量
BITPOS mykey 1 -- 返回第一个值为 1 或 0 的二进制位的位置
Redis的Bitmaps实际上就是字符串,它通过位操作命令来实现Bitmaps的功能。这种数据结构的优点是存储效率高,可以用来存储大量的二进制数据。
HyperLogLog是一种用于解决基数统计的算法,Redis从2.8.9版本开始增加了对HyperLogLog的支持。基数统计就是统计不同元素的数量。HyperLogLog的优点是,即使对数亿级别的数据进行基数统计,也只需要使用12KB的内存空间。
基本用法:
PFADD mykey element1 element2-- 添加指定元素到 HyperLogLog 中
PFCOUNT mykey-- 返回给定 HyperLogLog 的基数估算值
PFMERGE destkey sourcekey1 [sourcekey2]-- 将多个 HyperLogLog 合并为一个 HyperLogLog
Redis的地理空间索引功能是通过zset实现的,它可以存储经度、纬度、名称,然后对这些信息进行各种地理空间操作。
基本用法:
GEOADD mykey longitude latitude member-- 将给定的空间元素(纬度、经度、名字)添加到指定的键里面
GEODIST mykey member1 member2-- 返回两个给定位置之间的距离
GEOPOS mykey member-- 返回指定位置元素的位置(经度和纬度)
GEORADIUS mykey longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count]-- 查询指定半径内的位置元素
Redis 5.0引入了新的数据类型Streams,它是一个持久化的日志系统,每个条目都包含一个ID和一组键值对。Streams主要用于消息队列的场景,比如Kafka。
基本用法:
XADD mykey ID field1 value1 [field2 value2]-- 在stream里添加条目
XRANGE mykey start end [COUNT count]-- 返回ID在指定范围内的条目
XREAD [COUNT count] [BLOCK milliseconds] STREAMS key1 key2-- 从stream里读取条目