redis数据类型
redis存储的数据类型是和redis的作用直接挂钩的,我们首先要知道redis的出现是为了达到什么目标,从而知道redis中存储的数据应该是什么类型的,再根据redis中存储的数据类型来设计redis的数据类型。
我们知道reids的数据存储在内存中而不是磁盘,这么做是为了减少读取数据的时间,所以redis中一般都是存储一些高时效性的信息,例如一些热点新闻,或者是618或双11的商品库存之类的。
根据redis存储的数据类型我们设计了5中数据类型:
- string
- hash
- list
- set
- sorted_set/zset(应用性较低)
我们知道redis所有的数据都是采用key value的形式存储,而我们所说的数据类型一定是修饰value的,key永远都是字符串。
前面讲过redis使用help获取指令,其实这5个数据类型各自都是一个组,我们使用help + 空格 然后按table键就能查看组,例如我想要查看string类型的数据有什么操作,就可以在redis 命令行下输入help @string
c出现的所有命令都是对string的操作。
string
- 存储的数据:单个数据,最简单的数据存储形式,也是最常用的
- 存储数据的格式:一个空间保存一个数据
- 存储内容:通常用字符串,如果字符串以整数形式展示,可以作数字使用。
string基本操作
set key value
存数据get key
取数据del key
删除数据setnx key value
set not exist 存储据如果该key不存在的话mset key1 value1 key2 value2
一次存多个mget key1 key2
一次取多个strlen key
获取key对应value的长度append key value
在key对应的值后面追加value
string扩展操作
-
INCR key summary: Increment the integer value of a key by one since: 1.0.0
相当于对key对应的值 +1,但是对应的值必须是一个数字,否则会报错
value is not an integer or out of range
。如果incr 操作的key对应的value不存在的话,不会报错,而是会默认为0。incr后为 1。 -
INCRBY key increment summary: Increment the integer value of a key by the given amount since: 1.0.0
可以设置增加的值,例如
incrby key 2
就是增加2 了 -
INCRBYFLOAT key increment summary: Increment the float value of a key by the given amount since: 2.6.0
可以增加小数
-
DECR key summary: Decrement the integer value of a key by one since: 1.0.0
减一
-
DECRBY key decrement summary: Decrement the integer value of a key by the given number since: 1.0.0
减对应的值
-
SETEX key seconds value summary: Set the value and expiration of a key。expiration有 有效期,过期 的意思 since: 2.0.0
说一个例子可能就好理解了,我们使用短信验证登录的时候,收到验证码,同时会告诉我们5分钟内有效,其实就是用这个指令设置验证码并只存活5分钟。
setex code 300 123789
-
PSETEX key milliseconds value summary: Set the value and expiration in milliseconds of a key since: 2.6.0
和上面差不多,就是时间的单位不一样 ,下面的单位是毫秒级别的
redis所有操作都是原子性的,采用单线程。不会出现并发带来的影响
我们知道redis是非关系型的数据库,里面所有的数据都是独立的,这么做是为了提高速率,但是明显关系型的数据能让人更直观的知道数据的作用,所以们可以在key的命名上面做一些协商,可以通过key的名字一眼看出这个key对应的值是做什么用的。
key的命名格式一般为 表名 : 主键名 :主键值 : 字段名
hash
redis中的数据类型是根据需求制定的。前面的string虽然很好用了的,但是也有缺陷,那就是数据太散了,不好管理。当然我们也可以以json格式将多条数据存储到一个key value中,但是这么做的时候如果要修改某一个值,则需要修改整个value,效率很低。有没有什么数据结构既能方便管理,又不会降低数据操作速率呢?那就是我们接下来要讲的hash。其实我们在java中也学过hashmap,就是一个map,而我们知道redis也是一个map,好像有点绕,hash其实就是redis中的value为一个map。应该不难理解。
hash的基本操作
我们可以通help @hash
查看hash的所有操作。
hset key field value
添加/修改数据hget key field
获取数据hgetall key
获取整个hash的数据hdel key field1 [field2]
删除数据hsetnx key field value
设置值如果不存在hmset key field1 value1 field2 value2
获取同一个hash中多个field值hmget key field1 field2
设置同个hash中多个field值hlen key
获取hash字段的数量(不是hash的长度)hexists key field
获取hash表中是否存在指定字段
hash扩展操作
-
HKEYS key summary: Get all the fields in a hash since: 2.0.0
-
HVALS key summary: Get all the values in a hash since: 2.0.0
-
HINCRBY key field increment summary: Increment the integer value of a hash field by the given number since: 2.0.0
-
HINCRBYFLOAT key field increment summary: Increment the float value of a hash field by the given amount since: 2.6.0
hash操作注意事项:
hash中的value只能存储字符串,不存在嵌套现象
list
- 数据存储需求:存储多个数据,且对数据进入存储空间的顺序进行区分
- list类型:保存多个数据,底层使用双向链表存储结构实现
可以通过help @list
查看list的所有操作
list基本操作
-
lpush key value1 [value2]
从左边push元素前面将hash的时候有hset的命令,我们很容易想到前面的h就是hash的意思,所以在这里当我们看到
lpush
的时候我们也会自然而然的想到 l 就是list的缩写,但根据功能而言,这里的 l 应该是left。 -
rpush key value1 [value2]
从右边push元素 -
lrange key start stop
列举索引从start - stop的元素 ,如果stop为 -1 则表示末尾元素(把 - 号理解为倒数的意思,如果是-2 则代表倒数第二个) -
lindex key index
列举对应索引的元素 -
llen key
列举元素个数(不是长度) -
lpop key
从左边pop一个元素,和get有区别,pop后元素不再存在list中 -
rpop key
从右边pop一个元素
list扩展操作
-
LREM key count value summary: Remove elements from a list since: 1.0.0
第一次看到时不知道count代表什么,字面意思是 记数 的意思,其实就是数量的意思,我们知道list可以存储重复的值,所以我们可以选择删除几个元素。当count为0 的时候代表删除所有的该元素。
-
BLPOP key [key ...] timeout summary: Remove and get the first element in a list, or block until one is available since: 2.0.0
Remove and get the first element in a list就是
lpop
的功能,所以后面的描述就是b的功能,可以看到b应该是 锁 的意思。这条指令的意思是:从给定的key(一个或多个,如果有多个,则从左至右)中取出一个元素并删除,如果没有可取的元素,则等待最多timeout
时间。即如果在 等待时间内某个list中存入了元素,则取出并删除这个元素。 -
BRPOP key [key ...] timeout summary: Remove and get the last element in a list, or block until one is available since: 2.0.0
-
BRPOPLPUSH source destination timeout summary: Pop a value from a list, push it to another list and return it; or block until one is available since: 2.2.0
从右边pop,从左边push,source是第一个list的key,destination是第二个list的key。
set
和java中的set完全一样。
- 存储需求:存储大量数据,在查询方面提供更高的效率
- set类型:与hash类型完全相同,但是仅存储键,不存储值。
可以通过help @set
查看set的所有操作
set基本操作
sadd key member1 [member2]
添加元素smembers key
获取全部元素srem key member1 [member2]
删除元素scard key
获取集合数据总量sismember key member
判断集合中是否包含指定元素srandmember
随机获取集合元素spop
随机获取集合元素并移除该元素
前面说了set与hash完全相同,只是只存field不存value,那我们能不能先用sadd 创建一个set1,然后添加a,b,c三个元素,最后使用hget set1 a来获取一个nil值呢?我们尝试后发现会报错,(error) WRONGTYPE Operation against a key holding the wrong kind of value
看来是不行,那我们能不能再创建一个名为set1的hash结构呢?如果尝试过你会发现也不行,但是创建一个名为set1的string结构就没问题。但是我们会发现创建了名为set1的string后原来的set类型的set1就没有了,且不能再创建名为set1的set,由此可见数据类型之间也是有优先级的。
set扩展操作
-
SINTER key1 [key2 ...] summary: Intersect multiple sets。Intersect = 交叉,其实就是返回交集 since: 1.0.0
-
SUNION key1 [key2 ...] summary: Add multiple sets。返回并集 since: 1.0.0
-
SDIFF key1 [key2 ...] summary: Subtract multiple sets。返回只在key1中出现的元素 since: 1.0.0
-
SDIFFSTORE destination key [key ...] summary: Subtract multiple sets and store the resulting set in a key since: 1.0.0
-
SUNIONSTORE destination key [key ...] summary: Add multiple sets and store the resulting set in a key since: 1.0.0
-
SINTERSTORE destination key [key ...] summary: Intersect multiple sets and store the resulting set in a key since: 1.0.0
-
SMOVE source destination member summary: Move a member from one set to another since: 1.0.0
常用指令
前面的指令都是针对某个数据类型的指令,接下来我们就要学习redis的常用指令。
我们首先来想想在redis中我们需要什么指令呢?
前面存储了这么多东西,我们都能记住吗?如何知道某个key的类型呢?怎么查看我们已经存储的信息呢?
我们可以查看generic组中的命令,例如keys 命令就可以查看指定parrern的key,如keys *
就能查看所有的key,再通过type key 就能查看key对应的类型。更多的指令等你去发现哦~
-
del key
删除 -
exists key
检测是否存在 -
type key
返回key类型 -
SORT key [BY pattern] [LIMIT offset count] [GET pattern [GET pattern ...]] [ASC|DESC] [ALPHA] [STORE destination] summary: Sort the elements in a list, set or sorted set since: 1.0.0
-
rename key newkey
-
RENAMENX key newkey summary: Rename a key, only if the new key does not exist since: 1.0.0
-
SORT key [BY pattern] [LIMIT offset count] [GET pattern [GET pattern ...]] [ASC|DESC] [ALPHA] [STORE destination] summary: Sort the elements in a list, set or sorted set since: 1.0.0
-
EXPIRE key seconds summary: Set a key's time to live in seconds 。设置一个key的有效期,单位:秒 since: 1.0.0
-
PEXPIRE key milliseconds summary: Set a key's time to live in milliseconds设置一个key的有效期,单位:毫秒 since: 2.6.0
-
EXPIREAT key timestamp summary: Set the expiration for a key as a UNIX timestamp since: 1.2.0
-
ttl key
以毫秒单位获取可以的有效期 -
pttl key
以毫秒为单位获取key的有效期 -
PERSIST key summary: Remove the expiration from a key。移除一个key的时效性 since: 2.2.0
命名冲突及解决
前面我们已经发现key名字冲突问题了,redis同时有多人使用,命名冲突很常见,但怎么解决明明冲突的问题呢?
解决方案:
- redis默认为每个服务提供了16个数据库,编号从0 ~ 15,默认使用 0,可以在配置文件中修改数据库数量
- 每个数据库之间相互独立
-
select index
切换数据库 -
ping
-
MOVE key db summary: Move a key to another database。db就是目标数据库索引 since: 1.0.0
-
dbsize
获取当前数据库中元素数量 -
flushdb
清除当前数据库所有数据 -
flushall
清除所有数据库的数据。