redis 是一个高性能 key-value 数据库,但还支持多种数据结构的存储,比如 hash,set,list 等。redis 是一个内存数据库,常用用来做计数器,队列。mysql 可以理解是磁盘数据库,每张表对应的数据库目录下有 table_name.frm 文件,存储的是表定义信息,有 64kb 的限制,但是 mysql 有些临时表超过限制后也会存在内存中。redis 相对比 mysql

redis 是一个高性能 key-value 数据库,但还支持多种数据结构的存储,比如 hash,set,list 等。redis 是一个内存数据库,常用用来做计数器,队列。mysql 可以理解是磁盘数据库,每张表对应的数据库目录下有 table_name.frm 文件,存储的是表定义信息,有 64kb 的限制,但是 mysql 有些临时表超过限制后也会存在内存中。redis 相对比 mysql 而且更喜欢处理“热数据”,即需要快速查询或插入的数据。因为直接吃的是内存,所以跟磁盘相比,性能和成本需要考虑。

koa 如何连接 redis

const Koa = require('koa');
const Redis = require('ioredis');
const app = new Koa();
const session = require('koa-session2');
const { Store } = require('koa-session2');
// 配置文件
var config = {
  port: 6379,
  host: '127.0.0.1',
  db: 3,
  options: {
    return_buffers: false,
    auth_pass: ''
  }
};
// redis与session
class RedisStore extends Store {
  constructor(redisConfig) {
    super();
    this.redis = new Redis(redisConfig);
  }
  async get(sid, ctx) {
    let data = await this.redis.get(`SESSION:${sid}`);
    return JSON.parse(data);
  }
  async set(session, { sid = this.getID(24), maxAge = 1000000 } = {}, ctx) {
    try {
      await this.redis.set(`SESSION:${sid}`, JSON.stringify(session), 'EX', maxAge / 1000);
      return true;
    } catch (e) {
      return false;
    }
  }
  async destroy(sid, ctx) {
    return await this.redis.del(`SESSION:${sid}`);
  }
}
// redis的增删改查
class DraftRedis {
  constructor(redisConfig) {
    this.redis = new Redis(redisConfig);
  }
  async get(key) {
    let data = await this.redis.get(key);
    return JSON.parse(data);
  }
  async set(key, data, maxAge = 7 * 24 * 60 * 60 * 1000) {
    try {
      // Use redis set EX to automatically drop expired sessions
      await this.redis.set(key, JSON.stringify(data), 'EX', maxAge / 1000);
    } catch (e) {}
    return 'success';
  }

  async destroy(key) {
    return await this.redis.del(key);
  }
}
// 设置rediskey的生成时间
app.use(
  session({
    store: new RedisStore(config),
    ttl: 2 * 60 * 60 * 1000
  })
);
// redis的基本使用
app.use(async (ctx) => {
  let draftRedis = new DraftRedis(config);
  await draftRedis.set('DRAFTPSOTKEY', 'hello world');
  let redisPost = await draftRedis.get('DRAFTPSOTKEY');
  if (redisPost) {
    console.log(redisPost);
  }
  ctx.body = '连接redis';
});

app.listen(1111, () => {
  console.log('listen', 1111);
});
  • 在使用 redis 前,要确保自己开开启服务
  • koa-session2 的使用是为了设置 redis key 的 TTL
  • redis 我是用可视化工具 RedisDesktopManager 操作的

mysql 和 redis 同时使用

const Koa = require('koa');
const Redis = require('ioredis');
const mysql = require('mysql');
const app = new Koa();
const session = require('koa-session2');
const { Store } = require('koa-session2');
// 配置文件
var config = {
  port: 6379,
  host: '127.0.0.1',
  db: 3,
  options: {
    return_buffers: false,
    auth_pass: ''
  }
};
const mysql_config = {
  host: '127.0.0.1',
  user: 'root',
  password: '123',
  database: 'my_vue_blog',
  connectionLimit: 10
};
// 连接池
const pool = mysql.createPool({
  host: mysql_config.host,
  user: mysql_config.user,
  password: mysql_config.password,
  database: mysql_config.database,
  connectionLimit: mysql_config.connectionLimit
});
// 连接mysql
let query = (sql, values) => {
  return new Promise((resolve, reject) => {
    pool.getConnection((err, connection) => {
      if (err) {
        reject(err);
      } else {
        connection.query(sql, values, (err, rows) => {
          connection.release();
          if (err) {
            return reject(err);
          } else {
            return resolve(rows);
          }
        });
      }
    });
  });
};
// redis与session
class RedisStore extends Store {
  constructor(redisConfig) {
    super();
    this.redis = new Redis(redisConfig);
  }
  async get(sid, ctx) {
    let data = await this.redis.get(`SESSION:${sid}`);
    return JSON.parse(data);
  }
  async set(session, { sid = this.getID(24), maxAge = 1000000 } = {}, ctx) {
    try {
      await this.redis.set(`SESSION:${sid}`, JSON.stringify(session), 'EX', maxAge / 1000);
      return true;
    } catch (e) {
      return false;
    }
  }
  async destroy(sid, ctx) {
    return await this.redis.del(`SESSION:${sid}`);
  }
}
// redis的增删改查
class DraftRedis {
  constructor(redisConfig) {
    this.redis = new Redis(redisConfig);
  }
  async get(key) {
    let data = await this.redis.get(key);
    return JSON.parse(data);
  }
  async set(key, data, maxAge = 7 * 24 * 60 * 60 * 1000) {
    try {
      // Use redis set EX to automatically drop expired sessions
      await this.redis.set(key, JSON.stringify(data), 'EX', maxAge / 1000);
    } catch (e) {}
    return 'success';
  }

  async destroy(key) {
    return await this.redis.del(key);
  }
}
// 设置rediskey的生成时间
app.use(
  session({
    store: new RedisStore(config),
    ttl: 2 * 60 * 60 * 1000
  })
);
// 装载mysql
app.use(async (ctx, next) => {
  ctx.execSql = query;
  await next();
});
// redis的基本使用
app.use(async (ctx) => {
  let draftRedis = new DraftRedis(config);
  let result = await ctx.execSql(`show databases`);
  await draftRedis.set('DRAFTPSOTKEY', result);
  let redisPost = await draftRedis.get('DRAFTPSOTKEY');
  if (redisPost) {
    ctx.body = redisPost;
  }
});

app.listen(1111, () => {
  console.log('listen', 1111);
});
  • 当然也可以使用定时脚本,每天定时往数据库写入数据,node-schedule 这个插件就可以写定时脚本,比如
const schedule = require('node-schedule');
let rule = new schedule.RecurrenceRule();
rule.hour = 3;
rule.minute = 0;
schedule.scheduleJob(rule, async () => {
  // do somethings
});
  • 为什么要定时向 mysql 写入数据呢,举个例子,常见的点赞,取消点赞的高频次操作,每次都要读写数据库,大量的操作肯定会影响数据库的性能,所以就需要做缓存,缓存就是先放在 redis 中,比如每天晚上 12 点缓存一次,把点赞的数据存入 mysql 中,12 点前的点赞与点赞数据查询都在 redis 中完成。

暂无评论