NoSQL数据库(二)01-Redis数据类型——字符串类型之赋值与取值、递增数字、增加指定浮点数、向尾部追加值、获取字符串长度、设置键值 & 散列类型命令之赋值与取值、获取键值、删除字段、增加数字
了解过redis基础知识后,进入真正的redis世界。
- 获得符合规则的键名列表
KEYS pattern
keys会遍历redis中所有的键,当数量过多时会影响性能,不建议使用。
redis命令不区分大小写。
- 判断一个键是否存在
EXISTS key
如果键存在则返回整数类型1,否则返回0。
- 删除键
DEL key [key …]
可以删除一个或多个键,返回值是删除的键的个数。
如何删除多个key?
利用linux的管道 xargs。
- 获得键值的数据类型
redis>SET foo 1
OK
redis>TYPE foo
string
redis>LPUSH bar 1
(integer) 1
redis>TYPE bar
list
LPUSH命令的作用是向指定的列表类型键中增加一个元素,如果键不存在则创建它,后面会详细介绍。
扫描二维码关注公众号,回复: 15607228 查看本文章
字符串类型
介绍
字符串类型是Redis中最基本的数据类型,它能存储任何形式的字符串,包括二进制数据。你可以用其存储用户的邮箱、JSON化的对象甚至是一张图片。一个字符串类型键允许存储的数据的最大容量是512MB。
JSON化的对象: JSON.stringfy()
命令
- 赋值与取值
SET key value
- 递增数字
INCR num
SET foo bar
INCR foo
有同学可能会想到可以借助GET和SET两个命令自己实现incr函数,伪代码如下:
- 会通过 key取值
- 判断是否有值
- 如果没有就归 0, 有呢就进行+1操作
function incr($key) {
var $value = redis.get($key);
if(!$value) {
$value = 0;
} else {
$value = $value + 1; // $value = 5
return $value
}
}
如果 Redis 同时只连接了一个客户端,那么上面的代码没有任何问题(其实还没有加入错误处理,不过这并不是此处讨论的重点)。可当同一时间有多个客户端连接到Redis时则有可能出现竞态条件(race condition)[3] 。例如有两个客户端A 和B 都要执行我们自己实现的 incr 函数并准备将同一个键的键值递增,当它们恰好同时执行到代码第二行时二者读取到的键值是一样的,如“5”,而后它们各自将该值递增到“6”并使用 SET 命令将其赋给原键,结果虽然对键执行了两次递增操作,最终的键值却是“6”而不是预想中的“7”。这一部分跟 “事务”,举个例子: 付款与扣款,能讲整个流程的状态初始化。
ex: 文章访问量统计(标题, 正文,访问量)
博客的一个常见的功能是统计文章的访问量,我们可以为每篇文章使用一个名为post:文章ID:page.view的键来记录文章的访问量,每次访问文章的时候使用INCR命令使相应的键值递增。
- 以 post:文章id:page 存储文章信息
- 以post:文章id:page.view 存储访问量
Redis 对于键的命名并没有强制的要求,但比较好的实践是用“对象类型:对象ID:对象属性”来命名一个键,如使用键user:1:friends来存储ID为1的用户的好友列表。
// 字符串
// 存储过程
var redis = require('redis');
var client = new redis({
//一些配置
});
var $post_id = client.incr('post:count');
var $airticle = JSON.stringify({
title: 'hello',
content: 'world',
views: 0
})
// 赋值
client.set(`post:${
$post_id}:data ${
$airticle}`);
// 读取过程
var airticle = client.get('post:1:data');
var data = JSON.parse(airticle);
// 每次访问文章 都会调用
var $post_id = client.incr('post:count');
命令扩展
- 增加指定的整数
INCRBY key increment
- 减少指定的整数
DECR key
DECRBY key decrememt
- 增加指定浮点数
INCRBYFLOAT key increment
redis> INCRBYFLOAT bar 2.7 "6.7"
redis> INCRBYFLOAT bar 5E+4 "50006.69999999999999929"
- 向尾部追加值
APPEND key value
APPEND作用是向键值的末尾追加value。如果键不存在则将该键的值设置为value,即相当于 SET key value。返回值是追加后字符串的总长度。
- 获取字符串长度
STRLEN key
前面提到了字符串类型可以存储二进制数据,所以它可以存储任何编码的字符串。例子中Redis接收到的是使用UTF-8编码的中文,由于“你”和“好”两个字的UTF-8编码的长度都是3,所以此例中会返回6。
- 获取/设置多个键值
MGET
MSET
MSET key1 v1 key2 v2
MGET key1 key2
- 位操作
GETBIT key offset
SET foo bar
b,a,r 对应的ASCII码分别为98,97,114。转换成二进制分别为 1100010, 1100001, 1110010。
所有的文字: 英文 ,汉子,汉语,日语,符号。。。其实都是通过数字。
GETBIT foo 0
GETBIT foo 6
利用位操作可以非常紧凑的存储布尔值。比如如果需要存储 “男,女”。如果用数字0,1存储则需要 100万字节 约等于 1M, 但是如果用二进制存储只需要 100K左右, 只占用计算机的一个位。
再举个例子:
假如我们的id是从 1000000开始递增,我们则可以先减去1000000再进行递增存储,这样可以节约空间。
散列类型
假设我只想读取文章的标题,但是会需要把所有文章相关的信息都拿过来反序列化(标题,正文,阅读量。。。),会造成资源的浪费。
不仅读取有这个问题,修改也有这个问题。
所以,散列解决了这个问题。
介绍
散列适合存储对象:使用对象类别和ID构成键名,使用字段表示对象的属性,而字段值则存储属性值。
ex: 汽车数据模型
这是一种二维的数据结构。
回想 mysql数据库结构。
假设某些数据需要新增一个字段:
对于2,3这两天数据来说data是多余的,这样会变得越来越难维护。为了解决这个问题,必须新建额外的表进行关联。
而redis的散列类型不存在这个问题,我们可以为任何键新增或删除字段而不影响其它。
命令
- 赋值与取值
redis> HSET car price 500
(integer) 1
redis> HSET car name BMW
(integer) 1
redis> HGET car name "BMW"
HSET 命令的方便之处在于不区分插入和更新操作,这意味着修改数据时不用事先判断字段是否存在来决定要执行的是插入操作(update)还是更新操作(insert)。当执行的是插入操作时(即之前字段不存在)HSET命令会返回1,当执行的是更新操作时(即之前字段已经存在)HSET命令会返回0。更进一步,当键本身不存在时,HSET命令还会自动建立它。
2.获取键中所有的字段和值
redis> HGETALL car
1) "price"
2) "500"
3) "name"
4) "BMW"
不要担心结构不好用,在nodejs中会把返回值封装成js的object
redis.hgetall("car", function (error, car) {
//hgetall 方法的返回的值被封装成了 JavaScript的对象
console.log(car.price);
}
3.判断字段是否存在
HEXISTS key field
redis> HEXISTS car model
(integer) 0
redis> HSET car model C200
(integer) 1
redis> HEXISTS car model
(integer) 1
- 增加数字
HINCRBY key field increment
redis> HINCRBY person score 60
(integer) 60
5.删除字段
HDEL key field [field …]
redis> HDEL car price
(integer) 1
redis> HDEL car price
(integer) 0