本文共--字 阅读约--分钟 | 浏览: -- Last Updated: 2021-07-03
安装:brew install redis
mac
启动服务:nohup redis-server &
在Redis中是通过键来访问数据的,因此,可以将Redis想象成是JavaScript对象的方式存储数据的。Redis中的文档结构总是扁平的,举例来说,即使一个键包含类似哈希的JavaScript对象,却不能支持嵌套的数据结构。
Redis设计的初衷是内存存储,搭配可配置的磁盘持久化思路,所以速度很快,有一点很重要,需要记住:持久化到磁盘是很重要的,因为任何存储在内存中的东西都是不稳定的,而且会随着系统崩溃或者重启而受到影响。
Redis 查询语言,就好比 Redis 中的 SQL,首先确保服务器正常运行,随后执行如下命令。
# 与 Redis 服务器建立 telnet连接
redis-cli
# 设置一个值
redis 127.0.0.1:6379 > SET my.key test
OK
# 读取一个值
redis 127.0.0.1:6379 > GET my.key
test
# 返回所有的键
redis 127.0.0.1:6379 > KEYS *
1) "my.key"
对数字进行递增和递减
redis 127.0.0.1:6379 > SET online.users 0
OK
redis 127.0.0.1:6379 > INCR online.users
(integer) 1
redis 127.0.0.1:6379 > INCR online.users
(integer) 2
普通操作,如果要存储的数据下
{
"profile1": { "name": "Guillermo", "last": "Rauch"},
"profile2": { "name": "Tobi", "last": "Rauch"},
}
如何操作
# 设值 等同于 obj[profile1].name = 'Guillermo';
redis 127.0.0.1:6379 > HSET profile1 name Guillermo
# 获取一个指定哈希中所有的键和值
redis 127.0.0.1:6379 > HGETALL profile1
1) "name"
2) "Guillermo"
redis 127.0.0.1:6379 > HSET profile1 last Rauch
redis 127.0.0.1:6379 > HSET profile1 programmer 1
# 在哈希中删除一个键 等同于 delete obj[profile1].programmer
redis 127.0.0.1:6379 > HDEL profile1 programmer
# 检查某个字段是否存在 等同于 typeof obj[profile1].programmer != 'undefined'
redis 127.0.0.1:6379 > HEXISTS profile1 programmer
# 列表
# RPUSH push到右侧也就是列表的尾端 LPUSH push到左侧,也就是列表的顶端
redis 127.0.0.1:6379 > RPUSH profile1.jobs "job 1"
(integer 1)
redis 127.0.0.1:6379 > RPUSH profile1.jobs "job 2"
(integer 2)
# 获取指定返回的数组
redis 127.0.0.1:6379 > LRANGE profile1.jobs 0 -1
1) "job 1"
2) "job 2"
redis 127.0.0.1:6379 > LPUSH profile1.jobs "job 0"
redis 127.0.0.1:6379 > LRANGE profile1.jobs 0 -1
1) "job 0"
2) "job 1"
3) "job 2"
# 数据集
# 保存的是单个值(字符串),没有键。Redis允许在数据集、联合(union)获取到随机元素之间做交集操作
# 添加一个元素到数据集中 已存在的值不会重复添加
redis 127.0.0.1:6379 > SADD myset "a member"
(integer 1)
# 获取数据集的所有元素
redis 127.0.0.1:6379 > SMEMBERS myset
1) "a membe"
# 以相同的值再次调用 SADD不会发生任何事
redis 127.0.0.1:6379 > SADD myset "a member"
(integer 0)
redis 127.0.0.1:6379 > SMEMBERS myset
1) "a membe"
# 移除数据集中的某个元素
redis 127.0.0.1:6379 > SREM myset "a member"
为什么使用Redis来存储用户的session数据,而不是Node本身来存储,其中的原因是:
应用程序永远都无法享受到多线程带来的好处,如果存在Node中,随着应用程序负载不断增长,单进程无法承受所有的负载,需要将应用程序扩展到多进程或者多台计算机。
每次重启应用都会丢失session数据,比如:在部署新代码的时候总是需要重启的。
安装:npm install redis
需求:创建用户数据,用户与用户之间的关注、取关,用户查询自己的关注列表、粉丝列表、互粉列表。
// model.js
var redis = require('redis');
var client = redis.createClient();
/**
* 用户模型 id标识符 data数据 follows 关注 followers 粉丝
* 当 id1 关注了 id2
* Add user id "2" to the user id "1" follows
* Add user id "1" to the user id "2" followers
*/
function User(id, data) {
this.id = id;
this.data = data;
}
// 定义静态方法 用来从Redis查询结果中构建一个User实例
User.find = function (id, fn) {
client.hgetall("user:" + id + ":data", function (err, obj) {
if(err) return fn(err);
// 这个new至关重要,因为水合的时候就需要将获得的数据变成User对象,之后用来操作
fn(null, new User(id, obj));
})
}
// 添加save方法,用来创建和修改用户信息
User.prototype.save = function (fn) {
// 如果没有传入id 给一个随机数作为id
if (!this.id) {
this.id = String(Math.random()).substr(3);
}
// key value callback
client.hmset('user:' + this.id + ':data', this.data, fn);
}
// 点击关注:关注谁(id), 回调
User.prototype.follow = function (user_id, fn) {
client.multi()
.sadd('user:' + user_id + ':followers', this.id) // 将当前用户设置为被关注人的粉丝
.sadd('user:' + this.id + ':follows', user_id) // 将关注的人 添加当前用户的 关注列表中
.exec(fn);
// multi意味着告诉redis客户端 所有的命令必须等到exec执行后才能执行
}
// 取消关注
User.prototype.unfollow = function (user_id, fn) {
client.multi()
.srem('user:' + user_id + ':followers', this.id)
.srem('user:' + this.id + ':follows', user_id)
.exec(fn);
}
// 获取当前用户的粉丝列表
User.prototype.getFollowers = function (fn) {
client.smembers('user:' + this.id + ':followers', fn)
}
// 获取当前用户的关注列表
User.prototype.getFollows = function (fn) {
client.smembers('user:' + this.id + ':follows', fn)
}
// 获取互相关注的列表 即关注者和粉丝的交集
User.prototype.getFriends = function (fn) {
client.sinter('user:' + this.id + ':follows', 'user:' + this.id + ':followers', fn)
}
module.exports = User; // 导出模块
上面是用来构建模型,下面是测试功能的代码。
var User = require('./model');
// 创建测试用户
var testUsers = {
'mark@facebook.com': {"name": 'Mark Zuckerberg'},
'bill@microsoft.com': {"name": 'Bill Gates'},
'jeff@amazon.com': {"name": 'Jeff Bezos'},
'fred@fedex.com': {"name": 'Fred Smith'}
}
/**
*
* 用来创建用户的函数
* @param {Object} users data
* @param {Function} fn callback
*/
function create(users, fn) {
var total = Object.keys(users).length;
for (var key in users) {
(function (email, data) {
// 以邮箱作为id
var user = new User(email, data);
user.save(function (err) {
if(err) throw err;
--total || fn(); // 如果全部创建完成 就调用回调 total为0则代表全部创建完成
})
})(key, users[key])
}
}
/**
* 用于水合用户
* 水合:将testUsers 从 {'mark@facebook.com': {name: 'Mark Zuckerberg'}}
* 格式化为 User对象 {'mark@facebook.com': {id:'mark@facebook.com', data:{name: 'Mark Zuckerberg'}}}
* @param {*} users
* @param {*} fn
*/
function hydrate(users, fn) {
var total = Object.keys(users).length;
for (var key in users) {
(function (email) {
User.find(email, function (err, user) {
if(err) throw err;
console.log(user); // User { id: 'mark@facebook.com', data: { name: 'Mark Zuckerberg' } }
// 此时的user已经是User对象
users[email] = user;
--total || fn(); // 水合完成 调用回调
})
})(key)
}
}
// 正式创建并水合
create(testUsers, function () {
hydrate(testUsers, function () {
console.log(testUsers);
// 水合后,就可以测试模型上的其他操作了
testUsers['bill@microsoft.com'].follow('jeff@amazon.com', function (err) {
if(err) throw err;
console.log('+ bill followed jeff'); // 关注
testUsers['jeff@amazon.com'].getFollowers(function (err, users) {
if(err) throw err;
console.log('+ jeff\'s followers', users); // 获取粉丝列表
testUsers['jeff@amazon.com'].getFriends(function (err, users) {
if(err) throw err;
console.log('+ jeff\'s friends', users); // 获取互粉列表
testUsers['jeff@amazon.com'].follow('bill@microsoft.com', function (err) {
if(err) throw err;
console.log('+ jeff followed bill'); // 互粉
testUsers['jeff@amazon.com'].getFriends(function (err, users) {
if(err) throw err;
console.log('+ jeff\'s friends', users); // 再次获取互粉列表
})
// + bill followed jeff
// + jeff's followers [ 'bill@microsoft.com' ]
// + jeff's friends []
// + jeff followed bill
// + jeff's friends [ 'bill@microsoft.com' ]
})
})
})
})
})
})
// testUsers
// {
// 'mark@facebook.com': { id: 'mark@facebook.com', data: { name: 'Mark Zuckerberg' } },
// 'bill@microsoft.com': { id: 'bill@microsoft.com', data: { name: 'Bill Gates' } },
// 'jeff@amazon.com': { id: 'jeff@amazon.com', data: { name: 'Jeff Bezos' } },
// 'fred@fedex.com': { id: 'fred@fedex.com', data: { name: 'Fred Smith' } }
// }
// 使用redis查询
// 127.0.0.1:6379> KEYS *
// 1) "user:jeff@amazon.com:data"
// 2) "user:fred@fedex.com:data"
// 3) "user:mark@facebook.com:data"
// 4) "user:bill@microsoft.com:data"
// 127.0.0.1:6379> HGETALL "user:jeff@amazon.com:data"
// 1) "name"
// 2) "Jeff Bezos"