惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Forbes - Security
Forbes - Security
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
F
Fortinet All Blogs
B
Blog
T
The Blog of Author Tim Ferriss
Engineering at Meta
Engineering at Meta
GbyAI
GbyAI
Y
Y Combinator Blog
Microsoft Azure Blog
Microsoft Azure Blog
L
LangChain Blog
Recent Announcements
Recent Announcements
U
Unit 42
Martin Fowler
Martin Fowler
M
MIT News - Artificial intelligence
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
The Register - Security
The Register - Security
Recorded Future
Recorded Future
C
Check Point Blog
V
V2EX
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Hugging Face - Blog
Hugging Face - Blog
WordPress大学
WordPress大学
Google DeepMind News
Google DeepMind News
酷 壳 – CoolShell
酷 壳 – CoolShell
F
Full Disclosure
小众软件
小众软件
A
About on SuperTechFans
云风的 BLOG
云风的 BLOG
宝玉的分享
宝玉的分享
Last Week in AI
Last Week in AI
有赞技术团队
有赞技术团队
MongoDB | Blog
MongoDB | Blog
爱范儿
爱范儿
P
Proofpoint News Feed
罗磊的独立博客
量子位
D
Docker
博客园_首页
D
DataBreaches.Net
Project Zero
Project Zero
博客园 - 司徒正美
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
博客园 - Franky
Security Latest
Security Latest
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
N
Netflix TechBlog - Medium
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
博客园 - 三生石上(FineUI控件)
H
Hackread – Cybersecurity News, Data Breaches, AI and More
大猫的无限游戏
大猫的无限游戏

博客园 - LittlePeng

ffmpeg+x264 Windows MSVC 静态编译 NodeJS Addon 多线程通信 c coroutine leveldb(ssdb)性能、使用场景评估 [微信协议分析] 多媒体 [微信协议分析] 多点登陆 [微信协议分析] 文本消息 paxos(chubby) vs zab(Zookeeper) 分布式一致性算法 erlang 健壮性 tcp 出现rst情况整理 tcp_tw_reuse、tcp_tw_recycle 使用场景及注意事项 erlang 在线生成crashdump erlang 故障排查工具 erlang 虚机crash Erlang C1500K长连接推送服务-内存 Erlang C1500K长连接推送服务-性能 erlang 虚机性能调优 java问题排查总结
redis lua
LittlePeng · 2014-10-25 · via 博客园 - LittlePeng

  需求是在缓存最近一周内用户所有消息列表,考虑用Redis 存储;为每个存储一个独立Sorted Set,value 为消息体,Score 为MessageId,用以实现增量消息同步。

  问题就来了:Sorted Set 怎么清理?

    -设计内存容量只允许放一周内最新的,太久了缓存意义不大,太浪费。

    -再者存在百万级/s群发请求,不允许写入时触发清理。

  理想模型:如果使用磁盘则使用MyIsam堆表,数据按照顺序写入,再建立以uid为索引,删除却是完全顺序的。内存里面的话Hash 表 + RB 树两个维度索引,RB树可按照时间顺序清理。

  解决方案:

    - 写入第一条时,设置一周过期时间

      判断是否第一条:zadd key 0 0 value score 返回2 说明第一条,1 不是第一条,只是多一条0的数据

    - 用户每天第一次登陆,触发一次清理

      清理需要遍历Sorted Set上,消息一般不小,浪费io流量了,所以考虑采用lua 脚本实现。

    - 这样保证,通过pipeline只是高并发写入,同时保证活跃用户一周内消息都在内存(不活跃不保证),清理简单

清理脚本如下:

local ltime = 0
local dels = 0
local lefts = 0
local list = redis.call("ZRANGE", KEYS[1], 1, -1)
if(list[1] == nil) then
    return {-1, 0}
end
for _,v in ipairs(list) do
    if lefts == 0 then
        ltime = struct.unpack('<i', v)
        if ltime < tonumber(KEYS[3]) then
            dels = dels + 1
        else
            lefts = lefts + 1
        end
    else
        lefts = lefts + 1
    end
end
if lefts > tonumber(KEYS[2]) then
    dels = dels + (lefts - tonumber(KEYS[2]))
    lefts = tonumber(KEYS[2])
end
if lefts == 0 then
    ltime = 0
    redis.call("DEL", KEYS[1])
elseif dels > 0 then
    redis.call("ZREMRANGEBYRANK", KEYS[1], 1, dels)
end
return {dels, ltime}

  写入的消息前4byte 为little-endian 的UnixTime,Redis lua 支持struct,很简单解析出(当然也支持cjson,但速度要差一些).

  清理过期数据,并返回最后一条写入的时间,应用根据返回时间适当延长过期时间。

  这里因为考虑每个人消息一般不会太多,所以全部遍历,多的话可考虑分部分遍历,如10条10条来,最新的就不会被不必要的取出来了,怎么说遍历大Set还是较慢的。

clear_msgs(Uid, MaxLen, ExpireSec) ->
      ToExpires = utime() - ExpireSec,
      {ok, [Dels, LTime]} =
      eredis:q(pooler(Uid), [<<"EVAL">>, clear_script(), <<"3">>,
                              ?KEY_LIST(Uid), MaxLen, ToExpires]),
      {ok, binary_to_integer(Dels), binary_to_integer(LTime)}.

  性能:此段脚本在我机器上速度2.5w/s(列表长度10),  相比get 7w/s。速度很快,也节省网络流量。

    script load

  此段脚本有700多字节,每次执行会带来不少网络流量;但对性能影响较小,内部对于eval 会先sha1 脚本,从缓存获取生成好的lua 方法执行。

  当然最好使用script load,节省脚本传输、脚本的sha1计算,就行存储过程一样执行。

  luajit:

  github讨论过 ,redis lua,相比nginx_lua 更像数据库存储过程,提供事务性的多个相关性操作,是否使用jit区别不大;

      支持的库也很有限base、table、string、math、debug、cjson、struct、cmsgpack,能够做的事情不多,也尽量别把太多逻辑用lua写。

  redis.log 方法:

  调试大段的lua脚本,这个方法还是挺管用的。

  相关参考:

  官方说明:http://oldblog.antirez.com/post/scripting-branch-released.html

  源码分析:http://blog.nosqlfan.com/html/4099.html