rails基础-使用redis记录点赞数

为什么使用redis

社交平台每天的点赞操作都非常的多,如果每一次的点赞都写入数据库,对数据库而言是一个非常大的负担,因此使用redis记录点赞数,再每天定时写入库中做持久化是一个理想的解决方法。

redis 数据结构

redis中有5种数据结构,string、hash、list、zset、 set

结构类型 操作 存储的值 读写能力
string set get 字符串、整数、浮点数 对整个字符串或者字符串的其中一部分执行操作;整数和浮点数执行自增(increment)或者自减(decrement)
hash hmset hget hgetall hash散列,特别适合用于存储对象 添加、获取、移除单个键值对;获取所有键值对
list lpush lrange 链表,每个节点都包含一个字符串 从链表的两端推入或者弹出元素;读取单个或者多个元素;根据值来查找或者移除元素
set sadd smembers String 类型的无序集合,集合中不能出现重复的数据 添加、获取、移除单个元素;检查一个元素是否存在于某个集合中;计算交集、并集;获取集合中随机元素
zset zadd String 类型的有序集合

在rails项目中实现点赞统计

安装redis

# gemfile

gem 'redis'
gem 'redis-rails'

# bundle 

设置redis连接

# services/redis_client.rb
class RedisClient
    def self.current
      @redis_client ||= Redis.new(
          url: redis_url,               #redis 服务器地址
          password: redis_password      #redis 服务器密码
        )
    end
end

#接下来在项目中就可以使用RedisClient.current 去连接redis

模版

点赞需要记录 哪位用户(user) 对什么文章(article)点赞或取消点赞
需要记录 哪篇文章(article)点赞的总数 (thumbs_up_count)

RedisClient.current.hmset('thumbs_up', ["#{ariticle_id}#{user_id}", 0]])
RedisClient.current.set("thumbs_up
#{article_id}", up_count)

class User < ActiveRecord::Base

end

class Article < ActiveRecord::Base       #up_count 统计所有赞

end

class ThumbsUpLog < ActiveRecord::Base   # user_id article_id status 

end

操作

设定 1 为点赞 2 为取消点赞

class ArticleControllers < ApplicationController
    # @params article_id user_id operate
    def thumbs_up
        article_id, user_id = params[:article_id], params[:user_id]
        RedisClient.current.hmset("thumbs_up", ["#{article_id}_#{user_id}",operate ])
        if operate == 1
           RedisClient.current.incr("thumbs_up_#{article_id}")
        elsif operate == 2 && RedisClient.current.get("thumbs_up_#{article_id}") > 1
           RedisClient.current.decr("thumbs_up_#{article_id}")
        end
    end
end

定时任务

这里的定时任务采用之前写过的sidekiq-cron去实现

class SyncThumbsUpJob < ActiveJob::Base
    queue_as :default
    
    def perform
        Article.find_each do |a|
            up_count = RedisClient.current.get("thumbs_up_#{a.id}")
            a.udpate!(up_count: up_count)
        end
       
        sync_thumbs_up_log
        
    end
    
    def sync_thumbs_up_log 
        hash = RedisClient.current.hgetall('thumbs_up')
        hash.keys.each do |k|
            aritcle_id, user_id =  k.split('_')
            log = ThumbsUpLog.where(user_id: user_id, aritcle_id: aritcle_id).first_or_initialize
            log.udpate!(status: hash[k.to_sym])
        end
    end
end

总结

基本的思路如此: 将用户赞或取消赞都放到redis中,在设置一个定时任务去做数据持久化

后面都job感觉不理想,有感兴趣的说说好的思路吗

推荐阅读更多精彩内容

  • 十月,是一幅画,一阵凉风,三两朵白云,看眼中的深秋,飕飕不觉声,落叶悠悠舞,当我翻开书时,一朵菊香来,镜前便落下了...
    知更先生阅读 255评论 1 5
  • 时间总是让人猝不及防,小憩转醒,茶尚未凉,便已草木皆荒。 昨天的微风和暖阳转眼间就被甩到了十万八千里,阴冷的夜幕在...
    晓愁阅读 93评论 0 5
  • 光照在脸上 我就有了影子 街道是一个巨大的橱窗 里面车来车往 满目琳琅 我沐浴着阳光 揣测橱窗的里面,和更里面 思...
    深海的鲸看不见鱼阅读 51评论 0 0
  • 我有不少芳疗书籍,拿起这本,放下那本,云里雾里,又是懒人,到后来连翻书和看书都觉得麻烦。 兴致高昂的时候,捣鼓精油...
    花间拾记阅读 539评论 0 1