0%

Redis 和模型服务

Redis数据库 (JimDB数据库)

同其他kv数据库比较,Redis数据库优势:

  • 运行在内存中,支持数据持久化,磁盘在恢复数据时有作用
  • 支持 master-slave模式数据备份
  • 支持秒级过期时间
  • key只支持字符串;value支持多数据结构存储,eg. string, list, set, zset(有序集合), hash
  • 支持事务,操作原子性

场景

  • set, 用于标签服务查询
  • 用于特征服务查询
  • list, 用于服务器缓存(后端系统)
  • zset, 排行榜
  • hash, 存储、读取、修改用户属性

存储数据实操

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
if (saveToRedis) {
//创建redis client
val redisClient = new Jedis(redisEndpoint, redisPort)
val params = SetParams.setParams()
//设置ttl过期时间为24小时
params.ex(60 * 60 * 24)
//遍历存储embedding向量
for (movieId <- model.getVectors.keys) {
//key的形式为前缀+movieId,例如i2vEmb:361
//value的形式是由Embedding向量生成的字符串,例如 "0.1693846 0.2964318 -0.13044095 0.37574086 0.55175656 0.03217995 1.327348 -0.81346786 0.45146862 0.49406642"
redisClient.set(redisKeyPrefix + ":" + movieId, model.getVectors(movieId).mkString(" "), params)
}
//关闭客户端连接
redisClient.close()
}

线上服务与推荐系统

高并发推荐结构

负载均衡,提升服务能力

是高并发的基础,需要增加服务器来分配节点,“负载均衡服务器” 来分配不同服务器,采用高效 Nginx作为技术选型

缓存,降低服务压力

  • 增加缓存列表,同一用户多次请求
  • 新用户请求,从缓存列表中选择

服务降级

  • 采用最简单将降级服务
  • 缓存/内存中,产生推荐结果

搭建存储模块

特征分级存储

  • Cassandra(Nosql)高QPS 需求(JD场景:Hbase)
  • Redis(JimDB)
  • 内存
  • Mysql存储强一致性信息, eg. 物品是否可以被推荐这种控制类的信息,物品分类的层级关系,用户的注册信息

存储模块设计

  • HDFS,保存全量的离线特征和模型数据
  • Redis,保存线上所需特征和模型数据
  • 服务器内存,缓存频繁访问的特征

搭建线上服务实操

选择服务器技术框架

  • 嵌入式Java框架服务器Jetty
  • Tomcat适合搭建于工程项目
  • NodeJS
  • python
  • C++
  • Go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
public class RecSysServer {
//主函数,创建推荐服务器并运行
public static void main(String[] args) throws Exception {
new RecSysServer().run();
}
//推荐服务器的默认服务端口6010
private static final int DEFAULT_PORT = 6010;


//运行推荐服务器的函数
public void run() throws Exception{
int port = DEFAULT_PORT;
//绑定IP地址和端口,0.0.0.0代表本地运行
InetSocketAddress inetAddress = new InetSocketAddress("0.0.0.0", port);
//创建Jetty服务器
Server server = new Server(inetAddress);
//创建Jetty服务器的环境handler
ServletContextHandler context = new ServletContextHandler();
context.setContextPath("/");
context.setWelcomeFiles(new String[] { "index.html" });


//添加API,getMovie,获取电影相关数据
context.addServlet(new ServletHolder(new MovieService()), "/getmovie");
//添加API,getuser,获取用户相关数据
context.addServlet(new ServletHolder(new UserService()), "/getuser");
//添加API,getsimilarmovie,获取相似电影推荐
context.addServlet(new ServletHolder(new SimilarMovieService()), "/getsimilarmovie");
//添加API,getrecommendation,获取各类电影推荐
context.addServlet(new ServletHolder(new RecommendationService()), "/getrecommendation");
//设置Jetty的环境handler
server.setHandler(context);


//启动Jetty服务器
server.start();
server.join();
}

接口调用

1
http://localhost:6010/getmovie?id=1

返回值

1
{"movieId":1,"title":"Toy Story","releaseYear":1995,"imdbId":"0114709","tmdbId":"862","genres":["Adventure","Animation","Children","Comedy","Fantasy"],"ratingNumber":10759,"averageRating":3.9149549214611024,"topRatings":[{"rating":{"movieId":1,"userId":136,"score":5.0,"timestamp":1415635425}},{"rating":{"movieId":1,"userId":124,"score":5.0,"timestamp":1134475984}},{"rating":{"movieId":1,"userId":93,"score":5.0,"timestamp":835037871}},{"rating":{"movieId":1,"userId":84,"score":5.0,"timestamp":832543433}},{"rating":{"movieId":1,"userId":82,"score":5.0,"timestamp":1317331523}},{"rating":{"movieId":1,"userId":58,"score":5.0,"timestamp":1144058408}},{"rating":{"movieId":1,"userId":39,"score":5.0,"timestamp":859325696}},{"rating":{"movieId":1,"userId":34,"score":5.0,"timestamp":846509445}},{"rating":{"movieId":1,"userId":19,"score":5.0,"timestamp":855176628}},{"rating":{"movieId":1,"userId":6,"score":5.0,"timestamp":858275452}}]}

Welcome to my other publishing channels