第3章 Redis数据类型详解

3.1 Redis键/值介绍

Redis key值是二进制安全的,这意味着可以用任何二进制序列作为key值,从形如“foo”的简单字符串到一个JPG文件的内容都可以。空字符串也是有效key值。

关于key的几条规则:

  • 太长的键值不是个好主意,例如1024字节的键值就不是个好主意,不仅因为消耗内存,而且在数据中查找这类键值的计算成本很高。
  • 太短的键值通常也不是好主意,如果你要用“u:1000:pwd”来代替

user:1000:password,这没有什么问题,但后者更易阅读,并且由此增加的空间消耗相对于key object和value object本身来说很小。当然,没人阻止你一定要用更短的键值节省一丁点儿空间。

  • 最好坚持一种模式。例如:"object-type????field"就是个不错的注意,像这样“user:1000:password”。或者一个键值对的字段名中加上一个点,就想这样“comment????reply.to”。
127.0.0.1:6379> set user:01:passwd 99999
OK
127.0.0.1:6379> get user:01:passwd
"99999"

NoSQL数据库之redis持久化存储 (二)_数据类型

3.2 数据类型

3.2.1 String字符串类型

这是Redis最简单的数据类型之一。如果只使用这种数据类型,那么redis就是一个持久化的memcached服务器(注:memcache的数据仅保存在内存中,服务器重启后,数据将丢失)。当然redis对string类型的功能比memcached还是多很多的,我们来玩儿一下字符串类型:

(1)常规的String字符串类型

[root@redis01 scripts]# redis-cli -a yunjisuan set work ">9000"
OK
[root@redis01 scripts]# redis-cli -a yunjisuan get work
">9000"
  • 在redis中,我们通常用set设置一对key/value键值,然后用get来获取字符串的值。
  • value值可以是任何类型的字符串(包括二进制数据),例如你可以在一个键下保存一个jpg图片。但值的长度不能超过1GB
  • 虽然字符串是Redis的基本值类型,redis还支持更多对字符串的操作功能。

(2)String类型也可以用来存储数字,并支持对数字的加减操作。

[root@redis01 scripts]# redis-cli -a yunjisuan set counter 1
OK
[root@redis01 scripts]# redis-cli -a yunjisuan incr counter #自增1
(integer) 2
[root@redis01 scripts]# redis-cli -a yunjisuan incr counter
(integer) 3
[root@redis01 scripts]# redis-cli -a yunjisuan get counter
"3"
[root@redis01 scripts]# redis-cli -a yunjisuan incrby counter 2 #自增指定数值
(integer) 5
[root@redis01 scripts]# redis-cli -a yunjisuan incrby counter 2
(integer) 7
[root@redis01 scripts]# redis-cli -a yunjisuan get counter
"7"
[root@redis01 scripts]# redis-cli -a yunjisuan decr counter #自减1
(integer) 6
[root@redis01 scripts]# redis-cli -a yunjisuan decr counter
(integer) 5
[root@redis01 scripts]# redis-cli -a yunjisuan get counter
"5"
[root@redis01 scripts]# redis-cli -a yunjisuan decrby counter 2 #自减指定数值
(integer) 3
[root@redis01 scripts]# redis-cli -a yunjisuan decrby counter 2
(integer) 1
[root@redis01 scripts]# redis-cli -a yunjisuan get counter
"1"

INCR命令将字符串值解析成整型,将其加1,最后将结果保存为新的字符串值,类似的命令如下列表:

incr 自动自增加1 INCR key
incrby 自动自增指定数值 INCRBY key increment
decr 自动自减1 DECR key
decrby 自动自减指定数值 DECRBY key decrement

(3)为key设置新值并且返回原值

对字符串,另一个操作是GETSET命令,行如其名:他为key设置新值并且返回原值。这有什么用处呢?例如:你的系统每当有新用户访问时就用INCR命令操作一个Redis key。
你希望每小时对这个信息收集一次。你就可以GETSET这个key并给其赋值0并读取原值。

[root@redis01 scripts]# redis-cli -a yunjisuan
127.0.0.1:6379> set user01 zhangsan #设置新key-value
OK
127.0.0.1:6379> get user01      
"zhangsan"
127.0.0.1:6379> getset user01 wangwu    #设置新数据并返回旧数据
"zhangsan"
127.0.0.1:6379> getset user01 liliu     #设置新数据并返回旧数据
"wangwu"
127.0.0.1:6379> getset user01 gongli    #设置新数据并返回旧数据
"liliu"
127.0.0.1:6379> get user01      
"gongli"

(4)String类型还支持批量读写操作

127.0.0.1:6379> mset name zhangsan age 44
OK
127.0.0.1:6379> mget name age
1) "zhangsan"
2) "44"

(5)string类型还支持对其部分的修改和获取操作

127.0.0.1:6379> set images flower
OK
127.0.0.1:6379> get images
"flower"
127.0.0.1:6379> append images .jpg  #追加字符串
(integer) 10
127.0.0.1:6379> get images
"flower.jpg"
127.0.0.1:6379> strlen images
(integer) 10
127.0.0.1:6379> substr images 0 6
"flower."
127.0.0.1:6379> substr images 0 5
"flower"

命令使用帮助:

#查看单个命令help+命令名
127.0.0.1:6379> help set

  SET key value [EX seconds] [PX milliseconds] [NX|XX]
  summary: Set the string value of a key
  since: 1.0.0
  group: string

127.0.0.1:6379> help mset

  MSET key value [key value ...]
  summary: Set multiple keys to multiple values
  since: 1.0.1
  group: string

3.2.2 List类型

  • 要说清楚列表数据类型,最好先讲一点理论背景,在信息技术界List这个词常常被使用不当。例如“Python Lists”就名不副实(名为Linked Lists),但它们实际上是数组(同样的数据类型在Ruby中叫数组)
  • 一般意义上讲,列表就是有序元素的序列:10,20,1,2,3就是一个列表。但用数组实现的List和用Linked List实现的List,在属性方面大不相同。
  • redis lists基于Linked Lists实现。这意味着即使在一个list中有数百万个元素,在头部或尾部添加一个元素的操作,其时间复杂度也是常数级别的。用LPUSH命令在十个元素的list头部添加新元素,和在千万元素list头部添加新元素的速度相同。
  • 那么,坏消息是什么?在数组实现的list中利用索引访问元素的速度极快,而同样的操作在linked list实现的list上没有那么快。
  • Redis Lists用linked list实现的原因是:对于数据库系统来说,至关重要的特性是:能非常快的在很大的列表上添加元素。另一个重要因素是,正如你将要看到的:Redis lists能在常数时间取得常数长度。

Redis lists入门:

LPUSH命令可向list的左边(头部)添加一个新元素,而RPUSH命令可向list的右边(尾部)添加一个新元素。最后LRANGE命令可从list中取出一定范围的元素。

Redis能够将数据存储成一个列表,并能对这个列表进行丰富的操作:

127.0.0.1:6379> lpush students "zhangsan"   #将元素“zhangsan”放在students列表的最左边
(integer) 1
127.0.0.1:6379> lpush students "wangwu" #将元素“wangwu”插入列表的最左边
(integer) 2
127.0.0.1:6379> lpush students "liliu"  #将元素“liliu”插入列表的最左边
(integer) 3
127.0.0.1:6379> lrange students 0 2 #查看序列是0到2的元素
1) "liliu"
2) "wangwu"
3) "zhangsan"
127.0.0.1:6379> rpush students "wangyue"    #将元素wangyue插入列表的最右边
(integer) 4
127.0.0.1:6379> lrange students 0 3 #查看序列是0到3的元素
1) "liliu"
2) "wangwu"
3) "zhangsan"
4) "wangyue"
127.0.0.1:6379> llen students   #查看列表元素的个数
(integer) 4
127.0.0.1:6379> lpop students   #移除最左边的元素值
"liliu"
127.0.0.1:6379> rpop students   #移除最右边的元素值
"wangyue"
127.0.0.1:6379> lrange students 0 3 #列表里只剩下两个元素了
1) "wangwu"
2) "zhangsan"
127.0.0.1:6379> rpush students zhangsan
(integer) 3
127.0.0.1:6379> rpush students zhangsan
(integer) 4
127.0.0.1:6379> lrange students 0 3
1) "wangwu"
2) "zhangsan"
3) "zhangsan"
4) "zhangsan"
127.0.0.1:6379> lrem students 2 "zhangsan"  #删除列表里是“zhangsan”的元素,删除两次(从左向右删)
127.0.0.1:6379> lrange students 0 3
1) "wangwu"
2) "zhangsan"
127.0.0.1:6379> rpush students zhangsan
(integer) 2
127.0.0.1:6379> rpush students zhangsan
(integer) 3
127.0.0.1:6379> lrem students 1 "zhangsan"  #删除列表里的元素zhangsan一次
127.0.0.1:6379> lrange students 0 3
1) "wangwu"
2) "zhangsan"
3) "zhangsan"
127.0.0.1:6379> lrem students 0 "zhangsan"  #清空列表所有的zhangsan元素
127.0.0.1:6379> lrange students 0 3
1)