这一大段时间都没写文档,一方面是之前提到的在参与一个项目重构,全是坑搞得焦头烂额。另一方面是有准备跑路的打算,还有一方面是我这边在实现之前博客平台的前端部分,所以没写文章。等过段时间完成了会把实现的内容以文章的方式分享出来。
如果你还不知道怎么安装docker,你可以看我之前的文章:坏蛋Dan:docker简单入门
直接上代码,我们这里准备使用的是redisJSON
,也就是使用json
格式存储。但是redisJSON
的docker
包已经废弃了,所以我们这里使用redis/redis-stack
[1]
--requirepass
:这个是用来设置密码的,千万别忘了这一点,不然你就等着被注入病毒吧。。。。(别问我怎么知道的。。。)没有镜像会自动下载镜像。
这个时候你可以用docker ps -a
或者docker logs [container-name]
的方式看下是否正常安装。
这里我们需要接入两个包
redis
服务器的功能redis
池另外还需要
虽然是json
格式,但是传输还是得序列化。。。
下载完这仨
然后我们来接入,咱这里是基于之前我们实现的博客平台来接入,如果你对这个项目还不了解,可以看下这个索引:坏蛋Dan:Rust + Rocket + PostgreSQL简单实现CRUD的restfulAPI后台——索引
不过GitHub上的代码好久没更新了,里面还有些问题和bug,但大体设计还是差不多的。
首先,我们的这个redis需要放到全局,这样就不需要每次都去创建。
而在rocket
中,如果我们需要将某个东西放置全局,那么我们就需要用到State
。
回到我们之前的state
文件夹中。
ROCKET_REDIS
:这个是环境变量,我们需要手动在环境中添加,添加方式和我们数据库ROCKET_DB
变量一样的。格式为:redis://:[password]@[host]:[port]/
。比如你在powerShell
中运行我们的服务器,那么你就需要设置环境变量:$ENV:ROCKET_REDIS = 'redis://:[password]@[host]:[port]/';
这里我们是创建一个redis
池子,然后将它放置到全局。
接着我们去到main.rs
中引入这个state
。
那么这里就接入了,我们接着找一处地方使用下api
看能否正常连上。
这里就直接去到article/route.rs
文件中找到获取文章列表的route
。
这里代码我就不详细讲了,就是分页查询。
然后我们来接入redis
测试下能不能用。
首先我们在type
文件夹下创建一个cache_type.rs
的文件用于存储缓存的类型。
这里我们创建了一个CacheArticles
的 tuple struct
,用来存放我们缓存文章列表。然后我们需要给它实现FromRedisValue
这个trait
,为什么要这么做呢?因为我们需要告知redis
我们需要它返回的数据类型(当然,还是我们手动实现的,没办法自动判断)。
这里我们还得给Article
也实现FromRedisValue
,因为外层可以实现的原则是内部一定都实现了~
from_redis_value
:这是个function
,用来简化对redis::Value
的处理。我们可以稍微看下相关的源码FromRedisValue
macro
这里有两个宏,用来自动实现FromRedisValue
,但是很不巧,它没有被暴露出来,我们不能使用它。
而from_redis_value
则是FromRedisValue::from_redis_value
的简写,能快速返回一个处理好的Value
。
而我们还需要将数据从字符串转换回我们的struct
类型,所以我们需要手动去实现。即:
当然,也是需要申明类型的。
然后回到我们的route
里。
我们先来实现cache
部分。
这里我们在返回数据之前,将数据放到了redis
里。
使用json_set
的方法,这个方法会自动序列化,另外trait bound
需要我们实现Serialize
和Deserialize
这俩trait
,我们前面定义的时候已经通过派生宏的方式实现了。
这个方法会自动将我们的struct
序列化。
这里它实际上是调用的redis::cmd("JSON.SET")
的方式来实现的,这种方案也可以,不过繁琐一些。
不过你现在应该很疑惑,为啥你的代码提示没有提示这个api
,因为你没有引入几个重要的trait
。
这里我们需要手动引入AsyncCommands, JsonAsyncCommands, JsonCommands
这仨,不然就没办法使用json
相关的method
。
接着我们可以运行下代码看是否正常set
。
可以直接看下log
,或者我们也可以通过redis-cli
去查看是否set
进去了。
回到我们的docker
。
然后我们使用AUTH [your password]
的方式验证权限。
接着我们可以使用KEYS *
的方式查看
然后如果需要看具体的,redis
提供了六种类型。
我这里就不演示了(其实我遇到了问题,老是说类型有误。。。但是我存储的确实是字符串)
然后回到我们的代码中,我们接着来使用get
来看下缓存的数据。
这里使用的是json_get
的method
,注意这里需要声明类型CacheArticles
。
然后我们重新运行下我们的代码
可以看到正常拿到并且转换成我们的enum struct
类型了。
rust
中接入redis
的学习成本还是较高的。。。 我这边还是在摸索中,要完全接入还得思考很多问题。。
注意:实现FromRedisValue
的目的是为了转换成我们json_get
时需要的类型,所以这里不需要和json_set
是同一个类型。
比如我们有这么一个struct People { name: String; age: u8 }
。它将作为json_set
的类型,即你存储到redis
里的是{ name: 'xxx', age: xxx }
。
而在某个场景中,你只需要name
这个字段,这个时候你就不能使用People
这个类型了,而是应该使用String
作为它返回的类型,比如这样
而非这样
FromRedisValue
是用来处理返回数据的,所以如果你get
的数据结构和set
的不同,此时如果还使用同一个类型,就会导致报错。
由于一次性从缓存中将整个数组拿出来会临时占用大量的内存,所以最好的方式是拿必要的切片,这个时候我们也是可以使用json_get
来实现的,比如:
注意这里的$.list[start:end:steps]
,$
不可少,不然只会返回索引为start
的元素。
不过这里还有个问题,那就是这里会导致不走我们的CacheArticleSlice
的from_redis_value
,而是走的Article::from_redis_value
,问题的原因可能是我们这里使用的是json_get
的method
,所以它会认为只有一个。
所以这个时候我们需要修改下代码,避免涉及到Article
类型
这里实现FromRedisValue
的时候没有涉及Article
,则不会走Article::from_redis_value
。
发布于 2023-10-17 16:48・IP 属地广东