Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Discuss] client-side-cachin #15

Open
2881099 opened this issue Nov 10, 2020 · 5 comments
Open

[Discuss] client-side-cachin #15

2881099 opened this issue Nov 10, 2020 · 5 comments
Labels
Epic 提上日程特性 need : discuss 需要讨论

Comments

@2881099
Copy link
Owner

2881099 commented Nov 10, 2020

image

官方文档:https://redis.io/topics/client-side-caching

客户端缓存是一种用于创建高性能的技术。利用应用程序的可用内存,将 redis-server 信息的某些数据直接存储在应用程序端。

使用客户端缓存时,而无需再次请求 redis-server

FreeRedis 怎样提供 API 给使用者

目前功能已经走通,demo:https://github.com/2881099/FreeRedis/tree/master/examples/console_netcore31_client_side_caching

192.168.164.10:6379   > GET Interceptor01
sdflkjyuiyui
(1ms)

Not connected         > GET Interceptor01
sdflkjyuiyui
(0ms)

Not connected         > GET Interceptor01
sdflkjyuiyui
(0ms)

Not connected         > GET Interceptor01
sdflkjyuiyui
(0ms)

第一次从 redis-server 读取数据缓存到本地,后面的三次直接从本地内存读出来的数据。

因为本地内存有限,不能无限制将内容缓存起来。主要解决缓存条件。

  • 1、什么样的 key 才被缓存到本地(热点 key 的判断标准?)
  • 2、本地缓存使用什么类(字典?)
  • 3、缓存的容量对外怎么设置?
  • 4、本地缓存规则,xxx* 永久缓存? yyy* 缓存 60分钟?
  • 5、缓存删除通过,是 redis-server 推送订阅消息进行的,所以存在延后现象,比如我刚 Set("key1", xxx) 程序马上要 Get key1,读到的仍然是本地缓存数据。怎么解决,如果强制向 redis-server 读取数据的话,API 怎么设计
  • 6、加入布隆过滤器功能?

伪代码:

cli.UseClientSideCaching(new Options
{
     Policy = new [] {
          "xxxx*" : -1, 
          "yyy*": 60m
     }
});

欢迎踊跃发表意见

@NMSAzulX NMSAzulX added the need : discuss 需要讨论 label Nov 10, 2020
@NMSAzulX
Copy link
Collaborator

1、什么样的 key 才被缓存到本地(热点 key 的判断标准?)

该功能涉及到统计业务甚至动态逻辑,实时与定时等等维度,暂且想到设计之初仅提供 O(option)CURD 数据接口。


2、本地缓存使用什么类(字典?)

赞同 KV 模式保存,并发字典查询性能在 us 以下尚且可行,.NET5 中官方对字典以及字符串Key有特别优化。 目前最快的 KV 构建算法是 BTFTree 属于指针和动态代码的结合,使用 Emit 极难实现,除了实现树遍历和返回数据之外还需要对 if 分支做二分查找优化,此方案优先级极低。Swifter.Json 作者有实现 HashCode 版的二分查找,可提升性能。


3、缓存的容量对外怎么设置?

暂无好建议,更像是开放设置。


4、本地缓存规则,xxx* 永久缓存? yyy* 缓存 60分钟?

待调研,想到用守护线程来管理。

@NMSAzulX
Copy link
Collaborator

还需要评估一下 Tracking 和 广播 两种模式的使用场景和实现方式。

@NMSAzulX NMSAzulX added the need : investigate 需要调研 label Nov 10, 2020
@2881099
Copy link
Owner Author

2881099 commented Nov 10, 2020

广播处理起来太麻烦了,每个正在发送命令的 RedisSocket 都有可能收到消息,容易造成消息不对称。

目前是 client tracking redirect 1 同一个连接来完成这件事。

@NMSAzulX
Copy link
Collaborator

1、广播需要客户端来甄别数据。
2、重定向方案好。

看样子组播会好一点,如果官方能提供 UDP 客户端驱动来管理密钥和过期更新策略则极好。另外密钥传输场景像TFO的样子,目测有升级的余地,或许可以问问官方后期计划。

@2881099
Copy link
Owner Author

2881099 commented Nov 10, 2020

已完成如下功能,解决:

1、什么样的 key 才被缓存到本地(热点 key 的判断标准?)

交给外部处理,如下 KeyFilter 委托

2、本地缓存使用什么类(字典?)

使用并发字典

3、缓存的容量对外怎么设置?

交给外部处理,如下 Capacity 设置

4、本地缓存规则,xxx* 永久缓存? yyy* 缓存 60分钟?

交给外部处理,如下 CheckExpired 委托

5、缓存删除通过,是 redis-server 推送订阅消息进行的,所以存在延后现象,比如我刚 Set("key1", xxx) 程序马上要 Get key1,读到的仍然是本地缓存数据。怎么解决,如果强制向 redis-server 读取数据的话,API 怎么设计

内部已处理,本地执行命令之后,AOP 会删本地缓存,再次执行命令就不会从本地缓存读取了

6、加入布隆过滤器功能?

待续

如下测试,缓存目前主要解决 GET/MGET 的使用:

cli.UseClientSideCaching(new ClientSideCachingOptions
{
    //本地缓存的容量
    Capacity = 3,
    //过滤哪些键能被本地缓存
    KeyFilter = key => key.StartsWith("Interceptor"),
    //检查长期未使用的缓存
    CheckExpired = (key, dt) => DateTime.Now.Subtract(dt) > TimeSpan.FromSeconds(2)
});

cli.Set("Interceptor01", "123123"); //redis-server

var val1 = cli.Get("Interceptor01"); //redis-server
var val2 = cli.Get("Interceptor01"); //本地
var val3 = cli.Get("Interceptor01"); //断点等3秒 redis-server

cli.Set("Interceptor01", "234567"); //redis-server
var val4 = cli.Get("Interceptor01"); //redis-server
var val5 = cli.Get("Interceptor01"); //本地

var val6 = cli.MGet("Interceptor01", "Interceptor02", "Interceptor03"); //redis-server
var val7 = cli.MGet("Interceptor01", "Interceptor02", "Interceptor03"); //本地
var val8 = cli.MGet("Interceptor01", "Interceptor02", "Interceptor03"); //本地

cli.MSet("Interceptor01", "Interceptor01Value", "Interceptor02", "Interceptor02Value", "Interceptor03", "Interceptor03Value");  //redis-server
var val9 = cli.MGet("Interceptor01", "Interceptor02", "Interceptor03");  //redis-server
var val10 = cli.MGet("Interceptor01", "Interceptor02", "Interceptor03");  //本地

//以下 KeyFilter 返回 false,从而不使用本地缓存
cli.Set("123Interceptor01", "123123"); //redis-server

var val11 = cli.Get("123Interceptor01"); //redis-server
var val12 = cli.Get("123Interceptor01"); //redis-server
var val23 = cli.Get("123Interceptor01"); //redis-server

设置 cli.Notice 事件在控制台输出内容:

Not connected 代表没有经过 redis-server

192.168.164.10:6379   > CLIENT TRACKING ON REDIRECT 46
FreeRedis.RedisResult
(0ms)

192.168.164.10:6379   > SET Interceptor01 123123
OK
(24ms)

192.168.164.10:6379   > GET Interceptor01
123123
(2ms)

Not connected         > GET Interceptor01
123123
(0ms)

192.168.164.10:6379   > GET Interceptor01
123123
(0ms)

192.168.164.10:6379   > SET Interceptor01 234567
OK
(0ms)

192.168.164.10:6379   > GET Interceptor01
234567
(0ms)

Not connected         > GET Interceptor01
234567
(0ms)

192.168.164.10:6379   > MGET Interceptor01 Interceptor02 Interceptor03
[234567, Interceptor02Value, Interceptor03Value]
(0ms)

Not connected         > MGET Interceptor01 Interceptor02 Interceptor03
[234567, Interceptor02Value, Interceptor03Value]
(0ms)

Not connected         > MGET Interceptor01 Interceptor02 Interceptor03
[234567, Interceptor02Value, Interceptor03Value]
(0ms)

192.168.164.10:6379   > MSET Interceptor01 Interceptor01Value Interceptor02 Interceptor02Value Interceptor03 Interceptor03Value
False
(3ms)

192.168.164.10:6379   > MGET Interceptor01 Interceptor02 Interceptor03
[Interceptor01Value, Interceptor02Value, Interceptor03Value]
(1ms)

Not connected         > MGET Interceptor01 Interceptor02 Interceptor03
[Interceptor01Value, Interceptor02Value, Interceptor03Value]
(0ms)

192.168.164.10:6379   > SET 123Interceptor01 123123
OK
(0ms)

192.168.164.10:6379   > GET 123Interceptor01
123123
(0ms)

192.168.164.10:6379   > GET 123Interceptor01
123123
(0ms)

192.168.164.10:6379   > GET 123Interceptor01
123123
(0ms)

@NMSAzulX NMSAzulX added feature 加入特性池 Epic 提上日程特性 and removed feature 加入特性池 need : investigate 需要调研 labels Nov 27, 2020
@NMSAzulX NMSAzulX changed the title client-side-caching 功能讨论 [Discuss] client-side-cachin Dec 1, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Epic 提上日程特性 need : discuss 需要讨论
Projects
None yet
Development

No branches or pull requests

2 participants