当前位置:   article > 正文

Redis不常用操作指南(基于SpringBoot2,计算机专业毕设代码量要求

Redis不常用操作指南(基于SpringBoot2,计算机专业毕设代码量要求
  • 1.基于最小的单位bit进行存储,所以非常省空间。

  • 2.设置时候时间复杂度O(1)、读取时候时间复杂度O(n),操作是非常快的。

  • 3.二进制数据的存储,进行相关计算的时候非常快。

  • 4.方便扩容

4.2.1 预设需求

某平台有1E个用户,需要标记每个用户的在线状态

4.2.2 代码实现

package com.example.demo.redis;

import org.springframework.dao.DataAccessException;

import org.springframework.data.redis.connection.RedisConnection;

import org.springframework.data.redis.core.RedisCallback;

import org.springframework.data.redis.core.RedisTemplate;

import org.springframework.stereotype.Component;

import javax.annotation.Resource;

@Component

public class RedisBitMap {

@Resource

private RedisTemplate redisTemplate;

private static final String ONLINE_STATUS = “online_status”;

/**

  • 设置在线状态

  • @param userId

  • @param online

*/

public void setOnlineStatus(int userId, boolean online) {

redisTemplate.opsForValue().setBit(ONLINE_STATUS, userId, online);

}

/**

  • 统计在线人数

  • @return

*/

public Long getOnlineCount() {

return (Long) redisTemplate.execute((RedisCallback) con -> con.bitCount(ONLINE_STATUS.getBytes()));

}

}

复制代码

4.2.3 测试

package com.example.demo.redis;

import com.example.demo.ApplicationTests;

import org.junit.Test;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.beans.factory.annotation.Autowired;

public class RedisBitMapTest extends ApplicationTests {

@Autowired

RedisBitMap redisBitMap;

private static final Logger LOGGER = LoggerFactory.getLogger(RedisBitMapTest.class);

@Test

public void setOnlineStatusTest() {

// 10000个人

for (int i = 0; i < 10000; i++) {

// 设置偶数在线 奇数不在线

redisBitMap.setOnlineStatus(i, i % 2 == 0);

}

}

@Test

public void onlineCountTest() {

Long i = redisBitMap.getOnlineCount();

LOGGER.info(“oline count = {}”, i);

}

}

复制代码

4.3 HyperLogLog(需要掌握)


HyperLogLog,你可以把它的功能理解成一个优化了存储空间的Set,适合大型网站进行用户行为统计的业务场景,如果你是小型网站,用Set就行了;HyperLogLog计数统计是有一定的误差的,误差最大在1%以下,所以HyperLogLog不适用于百分百精确统计的场景,网站访问量统计通常也能接收这样的误差。

4.3.1 优缺点

  • 基数不大,数据量不大就用不上,会有点大材小用浪费空间

  • 有局限性,就是只能统计基数数量,而没办法去知道具体的内容是什么

4.3.2 示例代码

package com.example.demo.redis;

import cn.hutool.core.date.DateUtil;

import cn.hutool.core.date.TimeInterval;

import com.example.demo.ApplicationTests;

import org.junit.Test;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.data.redis.core.RedisTemplate;

import javax.annotation.Resource;

/**

  • RedisHyperLoglog对比Set

  • @author 热黄油啤酒

*/

public class RedisHyperLogLogTest extends ApplicationTests {

@Resource

private RedisTemplate<String, String> redisTemplate;

@Test

public void hllTest() {

TimeInterval timer = DateUtil.timer();

String key = “pv_hll:20211220”;

// 模拟1000次操作

for (int i = 1; i < 1000; i++) {

redisTemplate.opsForHyperLogLog().add(key, String.valueOf(i));

}

Long size = redisTemplate.opsForHyperLogLog().size(key);

LOGGER.info(“size = {}, 耗时= {}ms”, size, timer.interval());

// 操作999次返回996

}

@Test

public void setTest() {

TimeInterval timer = DateUtil.timer();

String key = “pv_set:20211220”;

// 模拟1000次操作

for (int i = 1; i < 1000; i++) {

redisTemplate.opsForSet().add(key, String.valueOf(i));

}

Long size = redisTemplate.opsForSet().size(key);

LOGGER.info(“size = {}, 耗时= {}ms”, size, timer.interval());

// 操作999次返回999

}

private static final Logger LOGGER = LoggerFactory.getLogger(RedisHyperLogLogTest.class);

}

复制代码

熟练使用Bitmap及HyperLogLog,结合redis自增数等操作,你就具备网站行为统计业务的技术基础了,下一步就可以去了解PV UV IP之类的统计业务需求,来动手做一个BI系统(行为识别behavior identity)

4.4 地理信息GEO(了解即可)


主流的数据库都提供了地理信息支持,包含存储、分析、数据生成等等,对于涉及地理信息相关业务产品,Redis GEO操作具有操作简单,高性能的优势,但是Redis的GEO只提供了点位的支持,缺乏对线和面的支持

4.4.1 代码示例

package com.example.demo.redis;

import org.springframework.data.geo.*;

import org.springframework.data.redis.connection.RedisGeoCommands;

import org.springframework.data.redis.core.RedisTemplate;

import org.springframework.stereotype.Component;

import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;

import java.util.ArrayList;

import java.util.HashMap;

import java.util.List;

import java.util.Map;

/**

  • 地理信息操作

*/

@Component

public class RedisGeo {

@Resource

private RedisTemplate redisTemplate;

private static final String CITY = “city”;

/**

  • 添加点位

  • @param name 名称

  • @param x 经度

  • @param y 纬度

*/

public void add(String name, double x, double y) {

redisTemplate.opsForGeo().add(CITY, new Point(x, y), name);

}

/**

  • 距离(km)

  • @param city1

  • @param city2

  • @return

*/

public double distance(String city1, String city2) {

Distance distance = redisTemplate.opsForGeo().distance(CITY, city1, city2, RedisGeoCommands.DistanceUnit.KILOMETERS);

return distance.getValue();

}

/**

  • 周边城市

  • @param city

  • @param distance

  • @return

*/

public List<Map<String, Object>> circum(String city, double distance) {

// 获取中心城市坐标

List positions = redisTemplate.opsForGeo().position(CITY, city);

List<Map<String, Object>> cityList = new ArrayList<>();

if (CollectionUtils.isEmpty(positions)) {

return cityList;

}

Point point = positions.stream().findFirst().get();

Circle circle = new Circle(point, new Distance(distance, Metrics.KILOMETERS));

RedisGeoCommands.GeoRadiusCommandArgs args = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs().includeDistance().includeCoordinates().sortAscending().limit(5);

GeoResults<RedisGeoCommands.GeoLocation> results = redisTemplate.opsForGeo()

.radius(CITY, circle, args);

for (GeoResult<RedisGeoCommands.GeoLocation> result : results) {

RedisGeoCommands.GeoLocation content = result.getContent();

String name = content.getName();

Point cityPoint = content.getPoint();

Distance cityDistance = result.getDistance();

// 为了展示这些api的使用,我将返回值包装成map

Map<String, Object> cityMap = new HashMap<>();

cityMap.put(“name”, name);

cityMap.put(“lng”, cityPoint.getX());

cityMap.put(“lat”, cityPoint.getY());

cityMap.put(“distance”, cityDistance.getValue());

cityList.add(cityMap);

}

return cityList;

}

}

复制代码

4.4.2 测试

package com.example.demo.redis;

import com.example.demo.ApplicationTests;

import org.junit.Test;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;

import java.util.Map;

public class RedisGeoTest extends ApplicationTests {

@Autowired

private RedisGeo redisGeo;

@Test

public void addTest() {

// 添加一些城市点位

redisGeo.add(“北京”, 116.405285, 39.904989);

redisGeo.add(“武汉”, 114.311582, 30.598467);

redisGeo.add(“郑州”, 113.631419, 34.753439);

redisGeo.add(“广州”, 113.271431, 23.135336);

redisGeo.add(“南宁”, 108.373451, 22.822607);

}

@Test

public void distanceTest() {

// 北京到武汉的距离

double distance = redisGeo.distance(“北京”, “武汉”);

LOGGER.info(“distance = {}km”, distance);

}

@Test

public void circumTest() {

// 北京周边1000km的城市

List<Map<String, Object>> circumCity = redisGeo.circum(“北京”, 1000);

LOGGER.info(“circum city = {}”, circumCity);

}

private static final Logger LOGGER = LoggerFactory.getLogger(RedisGeoTest.class);

}

复制代码

redis geo基本覆盖了主流的点位相关场景,比如附近的人,周边的店铺等等,我们熟悉这些api就可以解决这些需求了,没此类需求的也可当一个知识储备,如果你有更复杂的地理信息存储需求。

4.5 消息队列(了解即可)


Redis新的版本提供了官方的消息队列支持(当然这是Redis作者无奈的选择,毕竟太多人用Redis的List来处理消息了),我们介绍基于List的消息队列实现及官方提供消息队列

4.5.1 基于List

生产消费

package com.example.demo.redis;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.data.redis.core.RedisTemplate;

import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

import javax.annotation.Resource;

import java.util.concurrent.TimeUnit;

/**

  • 基于Redis List的消息队列实现

*/

@Component

public class RedisQueueOfList {

private static final Logger LOGGER = LoggerFactory.getLogger(RedisQueueOfList.class);

@Resource

private RedisTemplate<String, String> redisTemplate;

private static final String TOPIC = “redis_queue”;

/**

  • 发送消息

  • @param msg

*/

public void send(String msg) {

redisTemplate.opsForList().leftPush(TOPIC, msg);

}

@PostConstruct

public void listener() {

LOGGER.info(“消费者已启动…”);

new Thread() {

public void run() {

while (true) {

String msg = redisTemplate.opsForList().rightPop(TOPIC, 1, TimeUnit.SECONDS);

if (msg == null) {

continue;

}

// 业务处理

LOGGER.info(“queue msg = {}”, msg);

}

}

}.start();

}

}

复制代码

测试接口

package com.example.demo.redis.controller;

import com.example.demo.redis.RedisQueueOfList;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.web.bind.annotation.GetMapping;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;

@RestController

@RequestMapping(“redis-queue”)

public class RedisQueueController {

@GetMapping(“/send”)

public void send(String msg) {

queueOfList.send(msg);

}

@Autowired

private RedisQueueOfList queueOfList;

}

复制代码

基于Redis List的消息队列简单来说就是列表push, 消费者循环pop, 可以小规模使用,消息量的场景建议使用更加专业的消息队列中间件(kafka、rocketmq…)

4.5.2 Channel

Redis 发布订阅 (pub/sub) 是一种消息通信模式:发送者 (pub) 发送消息,订阅者 (sub) 接收消息。

生产及消费

package com.example.demo.redis;

import org.springframework.context.annotation.Bean;

import org.springframework.data.redis.connection.RedisConnectionFactory;

import org.springframework.data.redis.core.RedisTemplate;

import org.springframework.data.redis.listener.PatternTopic;

import org.springframework.data.redis.listener.RedisMessageListenerContainer;

import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;

import org.springframework.stereotype.Component;

import javax.annotation.Resource;

@Component

public class RedisChannel {

/**

  • 发送消息

  • @param msg

*/

public void send(String msg) {

redisTemplate.convertAndSend(CHANNEL, msg);

}

/**

  • 注册消息监听

  • @param connectionFactory

  • @param listenerAdapter

  • @return

*/

@Bean

public RedisMessageListenerContainer redisMessageListenerContainer(RedisConnectionFactory connectionFactory,

MessageListenerAdapter listenerAdapter) {

RedisMessageListenerContainer container = new RedisMessageListenerContainer();

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数同学面临毕业设计项目选题时,很多人都会感到无从下手,尤其是对于计算机专业的学生来说,选择一个合适的题目尤为重要。因为毕业设计不仅是我们在大学四年学习的一个总结,更是展示自己能力的重要机会。

因此收集整理了一份《2024年计算机毕业设计项目大全》,初衷也很简单,就是希望能够帮助提高效率,同时减轻大家的负担。
img
img
img

既有Java、Web、PHP、也有C、小程序、Python等项目供你选择,真正体系化!

由于项目比较多,这里只是将部分目录截图出来,每个节点里面都包含素材文档、项目源码、讲解视频

如果你觉得这些内容对你有帮助,可以添加VX:vip1024c (备注项目大全获取)
img

监听

  • @param connectionFactory

  • @param listenerAdapter

  • @return

*/

@Bean

public RedisMessageListenerContainer redisMessageListenerContainer(RedisConnectionFactory connectionFactory,

MessageListenerAdapter listenerAdapter) {

RedisMessageListenerContainer container = new RedisMessageListenerContainer();

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数同学面临毕业设计项目选题时,很多人都会感到无从下手,尤其是对于计算机专业的学生来说,选择一个合适的题目尤为重要。因为毕业设计不仅是我们在大学四年学习的一个总结,更是展示自己能力的重要机会。

因此收集整理了一份《2024年计算机毕业设计项目大全》,初衷也很简单,就是希望能够帮助提高效率,同时减轻大家的负担。
[外链图片转存中…(img-cSSACqNU-1712532552563)]
[外链图片转存中…(img-SiZKQUC5-1712532552564)]
[外链图片转存中…(img-b2KyG3wj-1712532552564)]

既有Java、Web、PHP、也有C、小程序、Python等项目供你选择,真正体系化!

由于项目比较多,这里只是将部分目录截图出来,每个节点里面都包含素材文档、项目源码、讲解视频

如果你觉得这些内容对你有帮助,可以添加VX:vip1024c (备注项目大全获取)
[外链图片转存中…(img-SApdegOh-1712532552565)]

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号