缓存同步那些事儿~

🎬 博客主页:楼下安同学的博客

🎥 本文由 楼下安同学 原创 🙉

🏅 欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!

📆生活明朗,万物可爱,人间值得,未来可期!✨

----❤️-----❤️-----❤️-----❤️-----❤️-----❤️-----❤️-----

前言

  我们知道,现在的Web项目都是前后端分离的,后端负责业务逻辑的处理,前端负责渲染数据等,当一页中需要展示的数据量过大的时候,我们就要用到分页,分页不仅可以提高用户体验,更重要的是可以降低数据库的压力,分页算法就是利用limit关键字来实现取数据,我们使用EXPLAIN关键字查询SQL的执行效率,发现随着数据量越来越大,查询数据越来越慢,究其原因是limit关键字在每一次操作的时候还是会遍历前面的数据,所以效率缓慢,查询资料得知,业界解决这一问题的方法是使用缓存,就是说在用户点击指定页码的时候,我么可以拿到这一页的最后一条数据,这一条数据我们可以存起来,点击下一页的时候我们再查缓存中的那条数据,从缓存中的那条数据开始取,这样就可以提高查询的效率。

实际问题

  继上文,我优化了分页算法,效率也提高了,可我们的数据是动态变化的啊,当我们向数据库新增一条数据的时候,缓存中的记录的数据还是没有改变,导致脏读数据,这是不允许的,所以我们要实时删除缓存的数据,然而代码执行是有顺序的,我们不能保证在代码执行过程中缓存中有新的数据进来,导致脏读。

  我们不能保证缓存数据和数据库实时都是一致的,但数据最终一致性是我们的结果,所以我们要做双删,就是再删一次,就能解决这一问题。

延时队列

  延时队列实际上就是一个轮询任务,每隔多长时间执行一次,可以控制间隔时长,今天选择redis实现延时队列。

为什么用Redis做延时队列

  • 消息持久化,消息至少被消费一次
  • 实时性:存在一定的时间误差(定时任务间隔)
  • 支持指定消息 remove
  • 高可用性
  • Redis 的特殊数据结构 ZSet 满足延迟的特性

实现

这里我们要测试脚本,由于导入的时候会执行一次,所以,我们分开写。

# delay_queue.py
import redis
import time


class DelayRedisQueue:
    """
    基于 Redis延时队列  有序集合
    """

    def __init__(self, key):
        self.key = key
        self.r = redis.Redis(decode_responses=True)

    # 入队
    def enqueue(self, uid, delay=0):
        self.r.zadd(self.key, {uid: time.time() + delay})

    # 出队
    def dequeue(self):
        res = self.r.zrangebyscore(self.key, 0, time.time(), start=0, num=1, withscores=False)
        if res:
            return res[0]
        else:
            return 0

    # 删除延时任务
    def remove(self, uid: int) -> None:
        return self.r.zrem(self.key, uid)
# 入队脚本
from delay_queue import DelayRedisQueue

if __name__ == '__main__':
    d = DelayRedisQueue("atx")
    d.enqueue(1,6)
# 出队脚本
import time
from delay_queue import DelayRedisQueue

if __name__ == '__main__':
    d = DelayRedisQueue("key")
    while 1:
        uid = d.dequeue()
        if uid:
            print(uid)
            d.remove(uid)
        time.sleep(1)

总结

  Redis 有序集合和集合一样也是string类型元素的集合,且不允许重复的成员。不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。有序集合的成员是唯一的,但分数(score)却可以重复。集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1),我们可以把当前的时间戳加上需要延长的时间作为score传入,利用zrangebyscore方法获取它就可以让它到那个时间点执行。
在这里插入图片描述

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

楼下安同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值