数据有序_Redis实战(3)-数据结构List实战一之商品信息的有序存储

摘要

电商平台的管理后端一般有两大角色的用户可以使用,一个是系统管理员,一个是平台的卖家/商家,对于商家而言,管理自个儿的商品是日常工作中再为普通不过的事情了,本文我们将以"有序存储并展示电商平台中商家上传的各式各样的商品列表",这里的关键词是"有序存储与展示",我们将借助缓存中间件Redis的数据结构~列表List进行实战实现!

内容

对于Redis的数据结构~列表List,在实际的项目开发实战中,也算是其中一种比较常见、应用也比较广泛的数据结构吧!

其底层数据存储结构跟JavaSE集合体系的List有极其相似之处,即数据在底层是有序、排好顺序的,在将列表的数据获取出来的时候,会发现其中的数据确实是已经排好顺序的了,给大家绘制了一个简单的List的存储和获取流程图,如下所示:

c16abfc3cb5814a06dcd4eb7c6338ef8.png

从该图中,可以看出,当我们往Redis的列表List中添加数据时,具有"先进先出"的特性,即所谓的"FIFO"(有点队列Queue的特性!),而且数据是紧凑、一个挨着一个存储的!

即当我们在往缓存Redis的列表List添加数据时,可以采用"LPush 即从左边的方向添加"的方式往缓存Redis的List中添加,然后再采用"LPop 即从左边的方向弹出数据"或者"RPop 即从右边的方向弹出数据"的方式获取这一有序存储的列表数据!

知道了列表List的数据存储和读取流程,其实我们也就几乎知晓了在实际的项目实战开发中的代码实现了。

下面我们以"电商平台~商家添加/下架商品时如何将其商品列表有序存储至缓存Redis的List中,每次获取商家当前的商品列表时可以直接从缓存中读取,减少每个商家在每次登陆之后都需要走数据库DB频繁查询 所带来的压力!"

(1)首先,当然是需要来个"产品信息表"啦,其完整的DDL(即数据定义语言)如下所示:

CREATE TABLE `product` (  `id` int(11) NOT NULL AUTO_INCREMENT,  `name` varchar(255) CHARACTER SET utf8mb4 NOT NULL COMMENT '商品名称',  `user_id` int(11) NOT NULL COMMENT '所属商户id',  `scan_total` int(255) DEFAULT NULL COMMENT '浏览量',  `is_active` tinyint(255) DEFAULT '1' COMMENT '是否有效',  PRIMARY KEY (`id`),  KEY `indx_scan_total` (`scan_total`) USING BTREE) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='商户商品表';

(2)然后,当然是需要开发一个Controller啦,在该Controller中我们需要开设两个请求方法,一个是给商户使用的"添加商品"(进DB,并塞入Redis),另外一个是获取当前商户已添加的"商品列表",其完整的源代码如下所示:

/** * 列表List实战-商户商品列表存储 * @Author:debug (SteadyJack) * @Link: weixin-> debug0868 qq-> 1948831260 * @Date: 2019/10/30 20:58 **/@RestController@RequestMapping("list")public class ListController extends AbstractController{    @Autowired    private ListService listService;    //添加    @RequestMapping(value = "put",method = RequestMethod.POST,consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)    public BaseResponse put(@RequestBody Product product,BindingResult result){        BaseResponse response=new BaseResponse(StatusCode.Success);        try {            log.info("--商户商品信息:{}",product);            response.setData(listService.addProduct(product));        }catch (Exception e){            log.error("--List实战-商户商品-添加-发生异常:",e.fillInStackTrace());            response=new BaseResponse(StatusCode.Fail.getCode(),e.getMessage());        }        return response;    }    //获取列表详情    @RequestMapping(value = "get",method = RequestMethod.GET)    public BaseResponse get(@RequestParam("userId") final Integer userId){        BaseResponse response=new BaseResponse(StatusCode.Success);        try {            response.setData(listService.getHistoryProducts(userId));        }catch (Exception e){            log.error("--List实战-商户商品-获取列表-发生异常:",e.fillInStackTrace());            response=new BaseResponse(StatusCode.Fail.getCode(),e.getMessage());        }        return response;    }}

(3)紧接着,我们需要开发Controller对应的Service,其职责当然是用来处理真正的业务逻辑,"添加商品"时,它负责将该商品信息添加进DB数据库,并添加进缓存Redis中;"获取商品"时,自然而然是从缓存Redis获取出List列表数据,其完整的源代码如下所示:

/** * 列表List服务 * @Author:debug (SteadyJack) * @Link: weixin-> debug0868 qq-> 1948831260 * @Date: 2019/10/30 9:48 **/@Servicepublic class ListService {    public static final Logger log= LoggerFactory.getLogger(ListService.class);    @Autowired    private ProductMapper productMapper;    @Autowired    private RedisTemplate redisTemplate;    //添加商品    @Transactional(rollbackFor = Exception.class)    public Integer addProduct(Product product) throws Exception{        if (product!=null){            product.setId(null);   //将该商品塞入数据库DB中            productMapper.insertSelective(product);            Integer id=product.getId();            if (id>0){  //将该商品塞入缓存Redis中                this.pushRedisService(product);            }            return id;        }        return -1;    }    //TODO:往缓存中塞信息-可以抽取到ListRedisService    private void pushRedisService(final Product product) throws Exception{        ListOperations listOperations=redisTemplate.opsForList();        listOperations.leftPush(Constant.RedisListPrefix+product.getUserId(),product);    }    //获取历史发布的商品列表    public List getHistoryProducts(final Integer userId) throws Exception{        List list= Lists.newLinkedList();        ListOperations listOperations=redisTemplate.opsForList();        final String key=Constant.RedisListPrefix+userId;        //TODO:倒序->userID=10010 ->Rabbitmq入门与实战,Redis入门与实战,SpringBoot项目实战        list=listOperations.range(key,0,listOperations.size(key));        log.info("--倒序:{}",list);        //TODO:顺序->userID=10010 ->SpringBoot项目实战,Redis入门与实战,Rabbitmq入门与实战        //Collections.reverse(list);        //log.info("--顺序:{}",list);        //TODO:弹出来移除的方式        //Product entity=listOperations.rightPop(key);        //while (entity!=null){            //list.add(entity);            //entity=listOperations.rightPop(key);        //}        return list;    }}

(4)至此,我们的代码实战就完毕了,最后我们就基于Postman进入测试环节吧,我们给商户10010添加两个商品吧,如下所示:

6a42ccceff1e5db815eb50df56ee027a.png
38e72fb6453d75accb0eafed2ed6687c.png

完成之后还可以前往数据库Mysql中查看刚刚已经添加完成的商品列表,如下图所示:

961f56ce6813b96641ccc4cca9b66c0c.png

最后,我们再在Postman发起"获取当前商户已经添加完成的商品列表-有序展示"(可以通过修改代码的方式,实现"顺序"、"倒序"等功效),如下所示:

1369b355f393788ea61bf22976050fc9.png

好了,本篇文章我们就介绍到这里了,建议各位小伙伴一定要照着文章提供的样例代码撸一撸,只有撸过才能知道这玩意是咋用的,否则就成了"空谈者"!

对Redis相关技术栈以及实际应用场景实战感兴趣的小伙伴可以前往Debug搭建的技术社区的课程中心进行学习观看: !

其他相关的技术,感兴趣的小伙伴可以关注底部Debug的技术公众号,或者加Debug的微信,拉你进"微信版"的真正技术交流群!一起学习、共同成长!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/460377.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

关于asp.net利用mono部署到Linux上的一些说明

linuxdot.net社区群:102732979(如果你认为你已经在.NET跨平台方面有足够的经验,请参加这个群:103810355)。 其中有各种大神,嘿嘿,如果你有问题可以来咨询,完全无偿的免费的。 mono的…

c单链表

#include <stdio.h>#include <stdlib.h>#define T 1#define F -1typedef int Type;struct Node{Type value;struct Node *next;};int init(struct Node **head); //初始化int insert_head(struct Node *head, Type value); // 头插法int in…

和redis_Redis 缓存

使用场景#Redis 通常用作web应用的内存缓存&#xff0c;和Django&#xff0c;Ruby-on-Rails&#xff0c;Node.js以及Flask框架结合Redis在存储新的数据的过程中可以清除陈旧的数据。Redis使用Less Recently Used(LRU)策略,可以为每个健设置过期时间Redis 存储指标数据用于量化网…

你好,C++(34)有一只叫做多利的羊 6.2.4 拷贝构造函数

6.2.4 拷贝构造函数 在C世界中&#xff0c;除了需要使用构造函数直接创建一个新的对象之外&#xff0c;有时还需要根据已经存在的某个对象创建它的一个副本&#xff0c;就像那只叫做多利的羊一样&#xff0c;我们希望根据一只羊创建出来另外一只一模一样的羊。例如&#xff1a…

invalid floating point operation什么意思_Point-MVSNet:基于多视角的点云重建网络

Point-Based Multi-View Stereo Network是一篇点云重建领域的文章&#xff0c;其工作内容为通过输入多张不同角度的图片&#xff0c;提取不同的点云特征&#xff0c;再进行融合&#xff0c;从而生成最终的点云。1.介绍Point-MVSNet的大致流程如下&#xff1a;首先生成一个粗略的…

在ubuntu 12.04上安装tomcat 7.40

因为源上的版本问题&#xff0c;所以没有使用源上的自动安装包&#xff0c;老规矩&#xff0c;Tomcat 7.0.40 Core下载地址&#xff1a;http://mirror.bit.edu.cn/apache/tomcat/tomcat-7/v7.0.40/bin /apache-tomcat-7.0.40.tar.gz 放入当前登录用户根目录: ~ 1、依旧是解压 t…

Nonblocking I/O 与 Asynchronous I/O

2019独角兽企业重金招聘Python工程师标准>>> Nonblocking IO 使用的是 polling &#xff08;轮询&#xff09;的方法&#xff08;主动去问&#xff09;&#xff0c; 而 异步IO 使用的是信号机制&#xff08;等待系统通知&#xff09; 转载于:https://my.oschina.ne…

锐浪报表数据源access_kylin+SuperSet实现实时大数据报表的快速开发

最近我的团队将报表计算引擎从阿里的OLAP分析中间价迁移到了kylin上&#xff0c;解决了非常多的问题&#xff0c;将一些我们的解决方案分享出来&#xff0c;希望对读者或者在用kylin的人有所帮助。一、 之前现状和问题之前我们系统的报表都是基于阿里云的相关组件开发的&#x…

结构体定义的三钟方式

#include <stdio.h>#include <string.h>structStudent{ intid; charname[ 20 ]; intage;} s3; //定义方式3&#xff0c;不常用的一种方式intmain(){ structStudent s1; //定义方式1s1.id 0 ; strcpy (s1.name, "Zhang" ); s1.age 20 ; stru…

极大似然估计 摘自维基百科

最大似然估计[编辑] 原文地址&#xff1a; http://zh.wikipedia.org/wiki/%E6%9C%80%E5%A4%A7%E4%BC%BC%E7%84%B6%E4%BC%B0%E8%AE%A1 最大似然估计&#xff0c;也称为最大概似估计&#xff0c;是一种统计方法&#xff0c;它用来求一个样本集的相关概率密度函数的参数。这个方…

unity改变图片像素大小_类动森像素画反向转换 (xBR)

起因前阵子沉迷动森&#xff0c;DIY 样式的画风真的超萌(&#xff9f;д&#xff9f;)&#xff89;&#xff0c;恰巧在推上看到有个小姐姐在讨论这个像素画转换的算法&#xff0c;就想在 Unity 里整整。最后实现的镜头特效效果如下图。像素缩放算法常见的像素缩放算法对比图如下…

【记忆化搜索】bzoj3208 花神的秒题计划Ⅰ

暴力 #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define N 701 const int dx[]{0,0,-1,1},dy[]{-1,1,0,0}; int n,mem[N][N],a[N][N],m; bool cant[N][N]; int f(int x,int y) {if(mem[x][y]) return mem[x][y];mem[x][…

c语言程序2

题目&#xff1a;有一分数序列&#xff1a;2/1&#xff0c;3/2&#xff0c;5/3&#xff0c;8/5&#xff0c;13/8&#xff0c;21/13...求出这个数列的前20项之和。1.程序分析&#xff1a;请抓住分子与分母的变化规律。2.程序源代码&#xff1a; #include "stdio.h" …

99 网络编程_传统网络工程师如何利用python实现公司内网IP地址信息查询?

网工圈网络工程师阿龙圈内最早的公益公众号,本号已认证&#xff01;学网络关注我一个就够了(关注近5w)关注听说99%的网工都来这里充电吖关注我&#xff0c;一个老HCIE(编号3558)带你轻松玩网络技术&#xff01; 交个朋友&#xff0c;一起和一个技术狂热者相互交流&#xff0c;共…

[原创]windows server 2012 AD架构试验系列 – 12 配置操作主机

[原创]windows server 2012 AD架构试验系列 – 12 配置操作主机ActiveDirectory支持域中所有域控制器之间的目录数据存储的多主机复制&#xff0c;因此域中的所有域控制器实质上都是对等的。ActiveDirectory支持域中所有域控制器之间的目录数据存储的多主机复制&#xff0c;因此…

应用沙盒

应用沙盒结构&#xff1a; 应用程序包&#xff1a;包含了所有的资源文件和可执行文件&#xff0c;这个压缩包的内容是不可以修改的。 Documents:保存应用程序运行时生成的需要持久化的的数据&#xff0c;ITunes同步设备时会备份该目录。 Library/Caches:保存应用程序运行时生成…

笔记本换内存条

步骤一 拆除护盖 笔记本内存插槽上都有护盖保护&#xff0c;首先第一步就是先将护盖拆掉。大多数笔记本的护盖上都有标识&#xff0c;有的是内凹的内存图形&#xff0c;而且从护盖的大小也能看出来&#xff0c;一般内存护盖的大小&#xff0c;就比内存条大一点。当然有不少笔记…

python更新es数据_python操作es增删改查

1.查询(search)# 获取案例库信息app.route(/get_dcn_cases, methods[GET, POST])def get_dcn_cases():# 告警事件数据dcn_cases_query {"_source": {"includes": ["faultName", "endTime", "startTime", "checked&quo…

angularJS 指令实践

AngularJS 指令&#xff08;Directives&#xff09;实践指南(1) 2014-03-12 10:22 陈鑫伟 编译 伯乐在线我要评论(0)字号&#xff1a;T|T一个指令用来引入新的HTML语法。指令是DOM元素上的标记&#xff0c;使元素拥有特定的行为。举例来说&#xff0c;静态的HTML不知道如何来创…

数据结构四双向链表

双向链表也叫双链表&#xff0c;是链表的一种&#xff0c;它的每个数据结点中都有两个指针&#xff0c;分别指向直接后继和直接前驱。所以&#xff0c;从双向链表中的任意一个结点开始&#xff0c;都可以很方便地访问它的前驱结点和后继结点。而之前的单链表为单向链表&#xf…