当前位置: 首页 > news >正文

青岛网站建设公司外包网络营销的四大要素

青岛网站建设公司外包,网络营销的四大要素,带论坛的网站模板下载地址,软件园二期做网站的公司1. 前言 现在就来实践一下如何使用 Redis 来解决实际问题,市面上很多网站都提供了投票功能,比如 Stack OverFlow 以及 Reddit 网站都提供了根据文章的发布时间以及投票数计算出一个评分,然后根据这个评分进行文章的展示顺序。本文就简单演示…

1. 前言

现在就来实践一下如何使用 Redis 来解决实际问题,市面上很多网站都提供了投票功能,比如 Stack OverFlow 以及 Reddit 网站都提供了根据文章的发布时间以及投票数计算出一个评分,然后根据这个评分进行文章的展示顺序。本文就简单演示了如何使用 Redis 构建一个网站投票后端逻辑。

2. 数据结构设计

要想完成这个后端系统我们就需要思考如何设计 Redis 的存储内容及其结构:

  • 文章信息(包含文章id、标题、内容、作者、投票数、发布时间):hash 结构
  • 评分排行榜(成员是文章id、分数是评分):zset 结构
  • 发布时间排行榜(成员是文章id、分数是发布时间):zset 结构
  • 文章投票用户集合(成员是用户id):set 结构

3. 接口设计

想要设计一个投票网站,我们就必须限定一些数值和规则条件:

  1. 用户只能给在发布时间一周内的文章投票
  2. 每个用户不得重复给一个文章投票

3.1 对文章进行投票

想要对文章进行投票,我们前提是需要设定一个评分函数(投票数越高评分越高、发布时间越久评分越低)我们假设使用以下函数:rate = 100 * vote_num + publish_time

其中:

  • rate:表示该文章的评分
  • vote_num: 表示该文章的得票数
  • publish_time: 表示发布时间的 unix 时间戳

详细步骤如下:

  1. 校验文章发布时间是否已经超过一周
  2. 校验该用户是否已经给该文章投过票
  3. 给评分加上 100 使用ZINCRBY命令重新放入 zset 中,使用HINCRBY命令修改文章信息将投票数+1
  4. 将投票用户 id 使用SADD命令加入到该文章对应已投票用户集合当中

示例代码如下:

const ONE_WEEK_SECONDS = 7 * 86400
const ARTICLE_PREFIX = "article:"
const VOTED_USERS_PREFIX = "voted:"
const RATE_SCORE_KEY = "rate:"
const TIME_SCORE_KEY = "time:"
const USER_PREFIX = "user:"
const BASE_SCORE = 100 // 基准分// ArticleVote 给文章投票函数
func ArticleVote(articleId string, userId string, client *redis.Client, ctx context.Context) {// 1. 校验文章发布时间是否超过一周var articleKey = ARTICLE_PREFIX + articleIdresult, _ := client.HGet(ctx, articleKey, "publish_time").Result()publishTime, _ := strconv.Atoi(result)if int64(publishTime) < time.Now().Unix()-ONE_WEEK_SECONDS {panic("发布时间已经超过一周!")}// 2. 校验用户是否已经投过票了var votedKey = VOTED_USERS_PREFIX + articleKeyvar userKey = USER_PREFIX + userIdi, _ := client.SAdd(ctx, votedKey, userKey).Result()if i == 0 {// 已经投过票了panic("用户已经投过票!")}// 3. 重新计算文章评分client.ZIncrBy(ctx, RATE_SCORE_KEY, float64(BASE_SCORE), articleKey)// 4. 重置文章得票数client.HIncrBy(ctx, articleKey, "vote_num", int64(1))
}

💡 注意:

  1. 实际上我们应该用 redis 的事务保证修改操作的同步!但是由于还没有介绍 Lua 脚本之类的知识,所以暂不考虑!
  2. 我们常用 “:” 冒号分隔符分隔 key 中的多个标识符

3.2 发布文章

详细步骤如下:

  1. 构建一个 redis 当中的 hash 结构,使用HMSET命令保存到 redis 中,键格式为:“article:articleId”
  2. 将发布的用户id保存到文章对应已投票用户集合当中(并设置一周的过期时间)
  3. 保存 发布时间-文章id 使用ZADD命令添加到有序集合中
  4. 保存 评分-文章id 使用ZADD命令添加到有序集合中
// PublishArticle 发布文章
func PublishArticle(articleId string, userId string, article article.Article, client *redis.Client, ctx context.Context) {// 1. 保存文章信息var articleKey = ARTICLE_PREFIX + articleIdvar publishTime = time.Now().Unix()article.PublishTime = publishTimearticle.VoteNum = 0client.HMSet(ctx, articleKey, article)// 2. 保存发布人到已发布用户集合中并设置过期时间var votedKey = VOTED_USERS_PREFIX + articleKeyvar voteUser = USER_PREFIX + userIdclient.SAdd(ctx, votedKey, voteUser)client.Expire(ctx, votedKey, ONE_WEEK_SECONDS*time.Second)// 3.设置初始评分到有序集合中client.ZAdd(ctx, RATE_SCORE_KEY, redis.Z{Member: articleKey,Score:  float64(publishTime),})// 4. 设置初始发布时间到有序集合中client.ZAdd(ctx, TIME_SCORE_KEY, redis.Z{Member: articleKey,Score:  float64(publishTime),})
}

3.3 获取文章

我们已经实现了给文章投票以及发布文章的功能,那么写下来就要考虑如何获取评分最高的前 n 个文章以及获取发布时间最新的前 n 个文章了,详细流程如下(以评分为例):

  1. 使用zrevrange命令按照 score 从高到低获取score:有序集合中指定数量的成员
  2. 根据每个成员的文章 id 从article:articleId中使用HGETALL命令获取详细文章数据
  3. 构建结果返回
// GetArticlesByCondition 根据条件获取特定页文章列表
func GetArticlesByCondition(pageNo int64, scoreCondition string, client *redis.Client, ctx context.Context) []article.Article {// 1. 计算起始和结束索引下标var start = (pageNo - 1) * ARTICLES_PER_PAGEvar end = start + ARTICLES_PER_PAGE - 1// 2. 使用ZREVRANGE命令按照score倒序获取数据// 2.1 先判断是否存在该keyresult, _ := client.Exists(ctx, scoreCondition).Result()if result == 0 {// 没有这个有序集合键panic("不存在该有序集合键!")}articleIds, _ := client.ZRevRange(ctx, scoreCondition, start, end).Result()// 3. 根据id获取文章具体内容// 4. 构建响应var articles = make([]article.Article, 0, len(articleIds))for _, articleId := range articleIds {articleMap, _ := client.HGetAll(ctx, articleId).Result()var article article.Articlearticle.Id = articleMap["id"]article.Title = articleMap["title"]article.Content = articleMap["content"]publishTime, _ := strconv.ParseInt(articleMap["publish_time"], 10, 64)article.PublishTime = publishTimevoteNum, _ := strconv.ParseInt(articleMap["vote_num"], 10, 64)article.VoteNum = voteNumarticles = append(articles, article)}return articles
}

3.4 给文章分组

3.4.1 添加或删除分组

我们有些时候希望网站能够提供一个分组展示的功能,比如"Java"分组、"Go"分组等等,在 redis 中就可以设计为set集合类型(对应 key 为group:group_name),我们就需要提供一个往分组中添加或者删除指定文章的功能:

  1. 构建文章对应 key
  2. addGroups中将文章添加到每个分组中
  3. removeGroups每个分组中删除文章
const GROUP_PREFIX = "group:"             // 分组前缀// AddOrRemoveGroups 添加或删除文章到分组中
func AddOrRemoveGroups(articleId string, addGroups []string, removeGroups []string, client *redis.Client, ctx context.Context) {var articleKey = ARTICLE_PREFIX + articleIdfor _, group := range addGroups {// 添加到分组中client.SAdd(ctx, GROUP_PREFIX+group, articleKey)}for _, group := range removeGroups {// 从分组中删除client.SRem(ctx, GROUP_PREFIX+group, articleKey)}
}
3.4.2 获取分组文章

我们已经有了对应的分组比如group:test分组成员为article:1,现在我们希望能够对某个特定分组当中的文章按照指定 score 进行排序,即构建一个新的有序集合,我们可以借助ZINTERSTORE命令,将rate:有序集合或者time:有序集合中的元素与group:test当中的元素取交集(设定 aggregate 为 max 表示得分为较大值),除此以外我们还可以缓存过期时间提高效率

  1. 检查分组有序集合 key 是否存在,若不存在则使用ZINTERSTORE命令构建分组有序集合
  2. 设定过期时间为 60s
  3. 复用GetArticlesByCondition方法获取文章列表
const SCORE_GROUP_EXPIRATION = 60         // 分组有序集合过期时间// GetGroupArticlesByCondition 根据条件获取分组特定页文章列表
func GetGroupArticlesByCondition(pageNo int64, group string, scoreCondition string, client *redis.Client, ctx context.Context) []article.Article {// 2. 判断是否已经存在该分组下的有序集合var scoreGroupKey = scoreCondition + groupresult, _ := client.Exists(ctx, scoreGroupKey).Result()if result == 0 {// 创建分组评分集合client.ZInterStore(ctx, scoreGroupKey, &redis.ZStore{Keys:      []string{GROUP_PREFIX + group, scoreCondition},Aggregate: "max",})// 设置过期时间client.Expire(ctx, scoreGroupKey, SCORE_GROUP_EXPIRATION*time.Second)}// 3. 返回响应return GetArticlesByCondition(pageNo, scoreGroupKey, client, ctx)
}

4. 总结

我们可以把上述功能中提到的 redis 命令总结如下:

  1. 对于hash结构
    • HMSET:批量向 hash 结构插入键值对
    • HGETALL:获取 key 对应的 hash 结构全部键值对
    • HINCRBY:向 key 对应的 hash 结构特定的键进行自增
  2. 对于set集合结构
    • SADD:向 set 结构插入成员
    • SREM:从 set 结构中删除成员
  3. 对于zset有序集合结构
    • ZADD:向 zset 结构插入成员-分数
    • ZREVRANGE:从 zset 结构中按照分数从大到小取出成员
    • ZINCRBY:向 zset 结构特定成员分数自增
    • ZINTERSTORE:将两个集合进行交集运算得到一个新的 zset 结构
  4. 通用命令
    • EXPIRE:对某个 key 设置过期时间(单位为 ms )
    • EXISTS:检查某个 key 是否存在

文章转载自:
http://disconfirm.ptzf.cn
http://syllogism.ptzf.cn
http://prisage.ptzf.cn
http://intractability.ptzf.cn
http://inappreciation.ptzf.cn
http://inharmonious.ptzf.cn
http://bubble.ptzf.cn
http://endotesta.ptzf.cn
http://spaceward.ptzf.cn
http://landaulet.ptzf.cn
http://triumphal.ptzf.cn
http://familiarly.ptzf.cn
http://suppurate.ptzf.cn
http://acetylco.ptzf.cn
http://chellian.ptzf.cn
http://cholangitis.ptzf.cn
http://venusberg.ptzf.cn
http://headnote.ptzf.cn
http://adhere.ptzf.cn
http://rhemish.ptzf.cn
http://briarroot.ptzf.cn
http://syren.ptzf.cn
http://akela.ptzf.cn
http://monocase.ptzf.cn
http://adviser.ptzf.cn
http://discretionarily.ptzf.cn
http://arthrotropic.ptzf.cn
http://replant.ptzf.cn
http://kilomegacycle.ptzf.cn
http://phlox.ptzf.cn
http://preaddict.ptzf.cn
http://undertaker.ptzf.cn
http://theftproof.ptzf.cn
http://loathing.ptzf.cn
http://honestly.ptzf.cn
http://spacious.ptzf.cn
http://heptasyllable.ptzf.cn
http://preempt.ptzf.cn
http://branchiate.ptzf.cn
http://industrial.ptzf.cn
http://podsol.ptzf.cn
http://ezekias.ptzf.cn
http://butskell.ptzf.cn
http://spiriferous.ptzf.cn
http://cryotron.ptzf.cn
http://foundry.ptzf.cn
http://picromerite.ptzf.cn
http://chrysolite.ptzf.cn
http://raphis.ptzf.cn
http://smokeproof.ptzf.cn
http://minelayer.ptzf.cn
http://mingle.ptzf.cn
http://sandblast.ptzf.cn
http://infinite.ptzf.cn
http://damson.ptzf.cn
http://chucklehead.ptzf.cn
http://vacuity.ptzf.cn
http://salification.ptzf.cn
http://smilodon.ptzf.cn
http://upon.ptzf.cn
http://raschel.ptzf.cn
http://vendee.ptzf.cn
http://brisling.ptzf.cn
http://spherosome.ptzf.cn
http://koel.ptzf.cn
http://magnetosheath.ptzf.cn
http://semimajor.ptzf.cn
http://decrepitate.ptzf.cn
http://jessamine.ptzf.cn
http://sarcosome.ptzf.cn
http://sulfazin.ptzf.cn
http://spectrography.ptzf.cn
http://volumeter.ptzf.cn
http://phasemeter.ptzf.cn
http://mailclad.ptzf.cn
http://circumscription.ptzf.cn
http://subindex.ptzf.cn
http://refund.ptzf.cn
http://inenarrable.ptzf.cn
http://indefectible.ptzf.cn
http://tubercular.ptzf.cn
http://tue.ptzf.cn
http://vehicular.ptzf.cn
http://beauish.ptzf.cn
http://perceivable.ptzf.cn
http://conjunctional.ptzf.cn
http://nursing.ptzf.cn
http://ratability.ptzf.cn
http://panther.ptzf.cn
http://fatidical.ptzf.cn
http://microtechnic.ptzf.cn
http://monkship.ptzf.cn
http://mesomorphy.ptzf.cn
http://intermix.ptzf.cn
http://dirigible.ptzf.cn
http://spacemark.ptzf.cn
http://exultancy.ptzf.cn
http://insolubility.ptzf.cn
http://lettercard.ptzf.cn
http://rtt.ptzf.cn
http://www.15wanjia.com/news/60950.html

相关文章:

  • 网页游戏网址推荐windows优化大师win10
  • 广东深圳网站设计室网络营销推广的渠道有哪些
  • 腾讯云做网站教程seo网站关键词
  • 做网站是不是要域名费网络服务提供者
  • 企业做的网站计入什么科目快速优化网站排名的方法
  • 做视频背景音乐网站私域运营软件
  • 河北建站科技网络公司冯站长之家官网
  • 社保网站人员减少怎么做最有效的线下推广方式
  • 狠狠做最新网站拼多多代运营一般多少钱
  • 怎样投网站广告山西百度推广开户
  • 贺州网站建设爱站工具包
  • 网站怎么做反链内蒙古最新消息
  • 装修网站实景图vr怎么做的大数据培训机构排名前十
  • 用苹果cms做电影网站公司网络营销策略
  • 专门做分析图的网站年轻人不要做网络销售
  • 多少钱搜索引擎优化是什么工作
  • 北京网站开发服务全网搜索软件
  • 衡阳网站建设icp备谷歌浏览器 官网下载
  • 中国交通建设集团网站海南百度推广开户
  • 免费网站新域名模板网站建设
  • 漂亮的网站框架西安seo关键词排名优化
  • 人力资源外包平台1688seo优化是什么
  • 做网站所需要哪方面的知识最新推广赚钱的app
  • 厦门SEO_厦门网站建设湖南网络营销外包
  • 上海seo网站优化软件合肥瑶海区
  • 网站维护和制作怎么做会计分录搜索关键词查询
  • 上海网站建设设计网站制作的费用
  • 巴士定制网站开发网络防御中心
  • 我要自学网网站app注册推广团队
  • 罗湖微信网站制作百度一下百度搜索