rails基础-使用redis记录点赞数
2019-07-14 本文已影响0人
葫芦葫芦快显灵
为什么使用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
定时任务
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感觉不理想,有感兴趣的说说好的思路吗