在日常开发中,我们一般都选择关系型数据库来存储数据,如MySQL,Oracle等,但是在并发量比较大的业务场景,关系型数据库往往会成为系统瓶颈,无法完全满足我们的需求,所以就诞生了非关系型数据库,即NoSQL数据库。
NoSQL数据库最常见的解释是“non-relational”,也有人解释为“Not Only SQL”。非关系型数据库不保证事务,也就是不具备ACID特性,这也是非关系型数据库和关系型数据库最大的区别,而我们即将介绍的Redis就属于NoSQL数据库的一种。
PS:本系列文章基于Redis5.0.5版本。
相比较于传统的关系型数据库,NoSQL数据库具有如下优点:
同时,NoSQL数据库的种类也非常多,按照不同的数据存储类型划分的话主要有以下常见的NoSQL数据库:
Redis全称:REmote DIctionary Service,即远程字典服务。Redis是一个开源的(遵守BSD协议)、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库。
Redis具有以下特性:
Redis当中采用key和value形式存储,key和value的最大长度限制是512M。
Redis默认有16个数据库,这个可以在配置文件redis.conf中做出修改:
databases 16
这16个数据库以编号0-15命名,不支持修改名字,而且各个数据库之间的数据并不具备隔离性,比如我们切换到任意一个数据库,执行命令flushall就可以清空所有数据库的数据,所以并不建议通过数据库来隔离不同的业务系统数据,但是我们可以针对同一个业务系统中的不同模块将其设置到不同的数据库中。
select 数据库编号
下面图示可以看到,我们是在0号数据库设值,所以切换到其他数据库中无法取到值:
flushdb
flushall
Redis中支持的数据类型到5.0.5版本为止,一共有9种。分别是:
虽然这里列出了9种,但是我们最常用的就是前面5种。
在Redis中,针对每种数据类型都提供了不同的类型的命令,下面就让我们依次来介绍一下。
字符串类型是我们使用最广泛的一种类型,而且Redis中的key值只能用字符串来存储,而value就可以支持9种数据类型。
Redis当中的字符串可以存储三种数据类型:
所以我们字符串类型的操作命令还包括了自增命令,下面我们来看一下字符串类型的常用操作命令
下面介绍几个常用的操作命令:
set key value
mset key1 value1 key2 value2
get key
get key1 key2
keys *
dbsize
exists key
rename oldKey newKey
del key
type key
incr key
incrby key 需要自增的数字
setnx key value # 设置单个key
mset key1 value1 key2 value2 # 设置多个key
PS:setnx和mset是原子操作,必须所有都设置成功才会返回true,其还有参数可以设置过期时间,一般分布式锁就是基于带过期时间的这个命令来实现的。
set key value EX|PX 18 # EX表示秒,PX表示毫秒
expire key
字符串类型的应用场景非常丰富,正常的热点数据都可以采用字符串类型来进行缓存,主要可以应用如下场景:
Redis中的List列表内部的元素也是字符串,我们可以将指定元素添加到列表中的指定位置。列表数据类型的操作命令一般都会有小写字母l开头。
来看一些常用的操作命令:
lpush key value1 value2
lpushx key value1 value2
lpop key
rpush key value1 value2
rpushx key value
rpop key
llen key
lindex key index
lrange key start stop
lset key index value
ltrim key start end
Redis中的集合是一个String类型的无序集合,集合中元素唯一不可重复。
Set集合的操作命令一般都以s开头,下面就列举一些常用的命令:
sadd key member1 member2
sismember key member
srem key member1 member2
smove source dest member
smembers key
Redis中的有序集合和集合的区别是有序集合中的每个元素都会关联一个double类型的分数,然后按照分数从小到大的顺序进行排列。
Sorted Sets集合的操作命令一般都以z开头,下面就列举一些常用的命令:
zadd key score1 member1 score2 member2
zscore key member
zincrby key num member
zcount key min max
zrange key start stop
zrevrange key start stop
zrangebyscore key min max
zrevrangebyscore key max min
zrank key member
zrevrank key member
zlexcount key min max
哈希表中存储的是一个key和value的映射表。操作哈希数据类型的命令一般都是h开头。
下面就是一些常用命令的示例:
hset key field value #设置单个field
hmset key field1 value1 field2 value2 #设置多个field
hsetnx key field value
hget key field
hmget key field1 field2
hdel key field1 field2
hlen key
hincrby key field increment
hincrbyfloat key field increment
hincrby key field increment
hkeys key
hvals key
哈希类型和字符串类型其实非常像,所以基本上字符串能做的事情,哈希都能做,而且在有些场景下利用哈希的分类存储,将会更加高效。
位图bitmap就是通过最小的单位bit来进行0或者1的设置,表示某个元素对应的值或者状态,其值只能是0或者1,表示是或者否。所以这个一般用于统计是否登录,是否收藏等非否即是的数据。
比如存储数据格式一般为:100110000111,这里的0和1就是bit值,设置的时候可以设置指定位置(偏移量)的bit值。
PS:位图的底层存储数据结构也是采用的字符串对象。
位图数据类型主要提供了以下命令:
setbit key offset value
getbit key offset
bitcount key [start] [end]
bitpos key bit [start] [end]
这个一般应用在非否即是的场景,比如说是否登录,用户是否留存,是否收藏商品,是否点赞等等。
HyperLogLog是Redis 2.8.9 版本新增的一种用来做基数统计算法的数据结构。其优点是在输入元素的数量或者体积非常大时,计算基数所需的空间总是固定的、并且是很小的。这种数据结构一般用于统计UV之类的信息。
HyperLogLog本身是一种算法,其来源于论文《HyperLogLog the analysis of a near-optimal cardinality estimation algorithm》,大家如果对这种算法感兴趣的可以去了解一下。
在Redis里面,每个HyperLogLog键只需要花费12KB内存,就可以计算接近2^64 个不同元素的基数,但是也可能有0.81%的错误率。
PS:HyperLogLogs的底层存储数据结构也是采用的字符串对象。
这种数据类型主要提供了以下三个命令:
pfadd key element1 element2
pfcount key1 key2
pfmerge destkey sourcekey1 sourcekey2
从上面我们可以看到,存进去之后并没有取出来的命令,所以这个一般就是用来统计,而且需要能接受误差。
比如上面的示例中,假如u1 u2 u3 u4就是用户id,那么我不需要判断,只要用户来访问一次网页我就存一次,最后通过pfcount取出来的值就是去重后的值(也就是上面所说的基数),虽然说有一定误差,但是像uv这种统计数据是可以接受误差的。
这个一般应用在可以接受误差场景的数据统计,比如说UV统计等场景
geospatial是Redis在3.2版本中新增的一种具有半径查询的地理空间索引数据类型。一般用来存储并计算两地之间的距离。
PS:HyperLogLogs的底层存储数据结构也是采用的有序集合对象。
以下就是一些常用命令:
geoadd key longitude latitude member
geopos key member1 member2
geodist key member1 member2 [unit]
georadius key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [ASC|DESC] [COUNT count]
georadiusbymember key member radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [ASC|DESC] [COUNT count]
最后两个命令基本上是一样的,一个是需要指定经纬度,一个是会自动读取某一个元素的经纬度。主要参数含义如下(单位就不重复介绍了):
这个应用场景就很明显了,只有需要计算地理位置相关的场景才会需要。
Streams是Redis5.0推出的一种数据类型。支持多播的可持久化消息队列,用于实现发布订阅功能,Streams的设计借鉴了kafka。Stream是Redis中最复杂的一种数据类型,在这里我们不展开介绍,后面介绍分布/订阅功能的时候再单独介绍这种数据类型及其强大复杂的操作API。
本文主要介绍了Redis中9种基本数据类型及其常用的操作命令和应用场景进行分析,Redis中的数据类型非常丰富,虽然大部分情况下字符串类型就够用了,但是在某些特定场景使用特定类型将会更加高效和优雅。
下一篇,我们将介绍一下Redis中数据类型底层的数据结构。
请关注我,和孤狼一起学习进步。