学习

使用 Redis 的移动银行帐户仪表板

Will Johnston
作者
Will Johnston, Redis开发人员增长经理
Prasan Kumar
作者
Prasan Kumar, Redis技术解决方案开发人员
GITHUB代码

以下命令用于克隆本教程中使用的应用程序的源代码

git clone --branch v1.2.0 https://github.com/redis-developer/mobile-banking-solutions

什么是移动银行账户仪表板?#

账户仪表板是移动银行应用程序中的一个页面,它会立即向用户显示账户重点信息。客户可以点击仪表板上的任何账户以查看实时账户详细信息,例如最新交易、剩余抵押贷款金额、支票和储蓄等。

账户仪表板将客户的财务状况集中在一个地方,方便查看。它降低了客户的财务复杂性,并培养了客户忠诚度。

以下图表是账户仪表板的数据架构示例

  1. 1.银行将信息存储在支持各个银行产品的多个独立数据库中
  2. 2.使用Redis数据集成 (RDI) 将银行产品组合中的关键客户账户详细信息(余额、近期交易)预取到Redis Cloud中
  3. 3.Redis Cloud为客户的账户仪表板提供支持,使移动银行用户能够在登录后立即查看余额和其他高优先级信息

为什么您应该在移动银行中使用Redis来创建账户仪表板?#

  • 弹性: Redis Cloud提供99.999%的正常运行时间和主动-主动地理分布,以防止关键用户配置文件数据的丢失
  • 可扩展性: Redis Cloud在极高的规模下提供< 1ms的性能,以确保应用程序在峰值负载下也能正常运行
  • JSON支持: 提供以Redis < 1ms的速度创建和存储账户信息作为JSON文档的能力
  • 查询和索引: Redis Cloud可以快速识别和存储来自多个不同数据库的数据,并对数据进行索引,使其易于搜索
注意

Redis Stack支持JSON数据类型,并允许您索引和查询JSON以及更多。因此您的Redis数据不限于简单的键值字符串化数据。

使用Redis构建账户仪表板#

注意

以下命令用于克隆本教程中使用的应用程序的源代码

git clone --branch v1.2.0 https://github.com/redis-developer/mobile-banking-solutions

下载上面的源代码并运行以下命令以启动演示应用程序

docker compose up -d

在docker启动并运行后,在浏览器中打开https://localhost:8080/ URL以查看应用程序

数据播种#

此应用程序利用Redis核心数据结构、JSON、TimeSeries、搜索和查询功能。播种的数据稍后用于显示可搜索的交易概述(具有实时更新),以及个人财务管理概述(具有实时余额和最大支出者更新)。

在应用程序启动时(在app/server.js中),会安排一个cron以定期创建随机银行交易并将这些交易播种到Redis中。

app/server.js
//cron job to trigger createBankTransaction() at regular intervals

cron.schedule('*/10 * * * * *', async () => {
  const userName = process.env.REDIS_USERNAME;

  createBankTransaction(userName);

  //...
});
  • 交易生成器会创建一个随机的银行借记或贷记,这将反映在(默认)的初始用户余额$100,000.00中
  • 交易数据作为JSON文档保存在Redis中。
  • 为了捕获随时间推移的余额,将balanceAfter值记录在TimeSeries中,其键为balance_ts,用于每次交易。
  • 为了跟踪最大支出者,在排序集bigspenders中的关联成员fromAccountName会增加交易金额。请注意,此金额可能是正数或负数。
app/transactions/transactionsGenerator.js
let balance = 100000.0;
const BALANCE_TS = 'balance_ts';
const SORTED_SET_KEY = 'bigspenders';

export const createBankTransaction = async () => {
  //to create random bank transaction
  let vendorsList = source.source; //app/transactions/transaction_sources.js
  const random = Math.floor(Math.random() * 9999999999);

  const vendor = vendorsList[random % vendorsList.length]; //random vendor from the list

  const amount = createTransactionAmount(vendor.fromAccountName, random);
  const transaction = {
    id: random * random,
    fromAccount: Math.floor((random / 2) * 3).toString(),
    fromAccountName: vendor.fromAccountName,
    toAccount: '1580783161',
    toAccountName: 'bob',
    amount: amount,
    description: vendor.description,
    transactionDate: new Date(),
    transactionType: vendor.type,
    balanceAfter: balance,
  };

  //redis json feature
  const bankTransaction = await bankTransactionRepository.save(transaction);
  console.log('Created bankTransaction!');
  // ...
};

const createTransactionAmount = (vendor, random) => {
  let amount = createAmount(); //random amount
  balance += amount;
  balance = parseFloat(balance.toFixed(2));

  //redis time series feature
  redis.ts.add(BALANCE_TS, '*', balance, { DUPLICATE_POLICY: 'first' });
  //redis sorted set as secondary index
  redis.zIncrBy(SORTED_SET_KEY, amount * -1, vendor);

  return amount;
};

使用RedisInsight查看bankTransaction数据示例

提示

下载RedisInsight以查看您的Redis数据或在工作台中使用原始Redis命令进行操作。

随时间推移的余额#

仪表板小部件

API端点

端点

/transaction/balance

代码位置

/routers/transaction-router.js

参数

返回值

[{x: timestamp, y: value}, ...]

余额端点利用时间序列,它返回时间序列对象balance_ts中的所有值范围。生成的范围将转换为一个对象数组,每个对象包含一个x属性(包含时间戳)和一个y属性(包含关联的值)。此端点为时间序列图表提供坐标,以绘制随时间推移的余额的可视化图表。

app/routers/transaction-router.js
const BALANCE_TS = 'balance_ts';

/* fetch transactions up to sometime ago */
transactionRouter.get('/balance', async (req, res) => {
  //time series range
  const balance = await redis.ts.range(
    BALANCE_TS,
    Date.now() - 1000 * 60 * 5, //from
    Date.now(), //to
  );

  let balancePayload = balance.map((entry) => {
    return {
      x: entry.timestamp,
      y: entry.value,
    };
  });

  res.send(balancePayload);
});

最大支出者#

仪表板小部件

API端点

端点

/transaction//biggestspenders

代码位置

/routers/transaction-router.js

参数

返回值

{labels:[...], series:[...] }

最大的支出者端点利用 排序集 作为二级索引,它检索排序集 bigspenders 中所有得分大于零的成员。返回前五个或更少的成员,以便为 UI 饼图提供数据。标签数组包含最大支出者的名称,系列数组包含与每个成员名称关联的数值。

app/routers/transaction-router.js
const SORTED_SET_KEY = 'bigspenders';

/* fetch top 5 biggest spenders */
transactionRouter.get('/biggestspenders', async (req, res) => {
  const range = await redis.zRangeByScoreWithScores(
    SORTED_SET_KEY,
    0,
    Infinity,
  );
  let series = [];
  let labels = [];

  range.slice(0, 5).forEach((spender) => {
    series.push(parseFloat(spender.score.toFixed(2)));
    labels.push(spender.value);
  });

  res.send({ series, labels });
});

搜索现有交易#

仪表板小部件

API端点

端点

/transaction/search

代码位置

/routers/transaction-router.js

查询参数

term

返回值

与 term 匹配的结果数组

搜索端点利用 搜索和查询,它从 UI 接收 term 查询参数。 Redis om Node 对字段 descriptionfromAccountName,和 accountType 的查询将触发并返回结果。

app/routers/transaction-router.js
transactionRouter.get('/search', async (req, res) => {
  const term = req.query.term;

  let results;

  if (term.length >= 3) {
    results = await bankRepo
      .search()
      .where('description')
      .matches(term)
      .or('fromAccountName')
      .matches(term)
      .or('transactionType')
      .equals(term)
      .return.all({ pageSize: 1000 });
  }
  res.send(results);
});

获取最近的交易#

仪表板小部件

API端点

端点

/transaction/transactions

代码位置

/routers/transaction-router.js

参数

返回值

结果数组

即使是交易端点也利用 搜索和查询。 Redis om Node 查询将触发并返回十个最新的交易。

app/routers/transaction-router.js
/* return ten most recent transactions */
transactionRouter.get('/transactions', async (req, res) => {
  const transactions = await bankRepo
    .search()
    .sortBy('transactionDate', 'DESC')
    .return.all({ pageSize: 10 });

  res.send(transactions.slice(0, 10));
});

准备在账户概览中使用 Redis 吗?#

希望本教程能帮助您了解如何在移动银行中使用 Redis 来构建账户概览,特别是针对移动银行的场景。有关此主题的更多资源,请查看以下链接。

其他资源#