设计思路
- 缓存策略:
- 本地缓存:在Flutter客户端使用内存缓存存储经常访问的数据,如最近查看的排行榜和个人成就数据。例如使用
shared_preferences
存储简单的缓存数据,对于复杂数据结构(如排行榜列表),可以在内存中维护缓存对象。
- 服务器端缓存:在服务器端(假设使用Node.js或其他后端技术)使用Redis作为缓存层。Redis具有高性能读写能力,适合处理高并发场景。当客户端请求数据时,首先检查Redis缓存中是否存在相应数据,如果存在则直接返回,减少对SQLite数据库的查询压力。
- 数据库连接池:
- 使用连接池技术管理与SQLite数据库的连接。在Flutter中,可以使用
sqflite
插件,它支持连接池功能。连接池可以避免每次查询都创建新的数据库连接,减少连接开销,提高查询效率。
- 数据一致性和缓存更新机制:
- 缓存失效策略:设置缓存过期时间,例如排行榜数据每5分钟更新一次缓存,个人成就数据在用户登录时更新缓存。当缓存过期后,再次请求数据时,从SQLite数据库查询最新数据并更新缓存。
- 主动更新缓存:当游戏数据发生变化(如玩家获得新成就),不仅要更新SQLite数据库,还要主动更新Redis缓存和客户端本地缓存,确保数据一致性。
关键代码结构
- Flutter客户端缓存代码示例(使用
shared_preferences
):
import 'package:shared_preferences/shared_preferences.dart';
class LocalCache {
static Future<void> saveData(String key, dynamic value) async {
final prefs = await SharedPreferences.getInstance();
if (value is String) {
await prefs.setString(key, value);
} else if (value is int) {
await prefs.setInt(key, value);
} else if (value is bool) {
await prefs.setBool(key, value);
}
}
static Future<dynamic> getData(String key) async {
final prefs = await SharedPreferences.getInstance();
return prefs.get(key);
}
}
- 服务器端Redis缓存代码示例(使用Node.js和
ioredis
库):
const Redis = require('ioredis');
const redis = new Redis();
async function getFromRedis(key) {
return await redis.get(key);
}
async function setToRedis(key, value, expiration = 300) {
await redis.setex(key, expiration, value);
}
- Flutter数据库连接池代码示例(使用
sqflite
):
import 'package:sqflite/sqflite.dart';
import 'package:path/path.dart';
class DatabaseHelper {
static final DatabaseHelper instance = DatabaseHelper._init();
static Database? _database;
DatabaseHelper._init();
Future<Database> get database async {
if (_database != null) return _database!;
_database = await _initDB('game.db');
return _database!;
}
Future<Database> _initDB(String filePath) async {
final dbPath = await getDatabasesPath();
final path = join(dbPath, filePath);
return await openDatabase(path, version = 1, onCreate: _createDB);
}
Future<void> _createDB(Database db, int version) async {
// 创建表等数据库初始化操作
const idType = 'INTEGER PRIMARY KEY AUTOINCREMENT';
const textType = 'TEXT NOT NULL';
const intType = 'INTEGER NOT NULL';
await db.execute('''
CREATE TABLE achievements (
id $idType,
player_id $intType,
achievement_name $textType
)
''');
}
Future<List<Map<String, dynamic>>> query(String table) async {
final db = await instance.database;
return await db.query(table);
}
}
- 缓存更新和数据一致性维护代码示例:
- Flutter客户端:当接收到服务器推送的游戏数据更新消息时,更新本地缓存和请求服务器更新Redis缓存。
// 假设收到成就更新消息
void handleAchievementUpdate(Map<String, dynamic> achievementData) {
// 更新本地缓存
LocalCache.saveData('achievement_${achievementData['player_id']}', achievementData);
// 发送请求到服务器更新Redis缓存
// 这里假设使用http库发送请求
http.post(Uri.parse('http://your-server-url/update_redis_achievement'),
body: achievementData);
}
- 服务器端:当接收到客户端更新请求时,更新SQLite数据库和Redis缓存。
// 假设使用Express框架
const express = require('express');
const app = express();
app.use(express.json());
app.post('/update_redis_achievement', async (req, res) => {
const achievementData = req.body;
// 更新SQLite数据库
// 这里假设使用sqlite3库操作SQLite数据库
const sqlite3 = require('sqlite3').verbose();
const db = new sqlite3.Database('game.db');
const query = 'UPDATE achievements SET achievement_name =? WHERE player_id =?';
db.run(query, [achievementData.achievement_name, achievementData.player_id], function (err) {
if (err) {
console.error(err);
res.status(500).send('Database update failed');
} else {
// 更新Redis缓存
setToRedis(`achievement_${achievementData.player_id}`, JSON.stringify(achievementData));
res.status(200).send('Achievement updated successfully');
}
});
db.close();
});