赞
踩
1.基于最小的单位bit进行存储,所以非常省空间。
2.设置时候时间复杂度O(1)、读取时候时间复杂度O(n),操作是非常快的。
3.二进制数据的存储,进行相关计算的时候非常快。
4.方便扩容
某平台有1E个用户,需要标记每个用户的在线状态
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()));
}
}
复制代码
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不适用于百分百精确统计的场景,网站访问量统计通常也能接收这样的误差。
基数不大,数据量不大就用不上,会有点大材小用浪费空间
有局限性,就是只能统计基数数量,而没办法去知道具体的内容是什么
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只提供了点位的支持,缺乏对线和面的支持
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;
}
}
复制代码
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的消息队列实现及官方提供消息队列
生产消费
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;
/**
*/
@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…)
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年计算机毕业设计项目大全》,初衷也很简单,就是希望能够帮助提高效率,同时减轻大家的负担。
既有Java、Web、PHP、也有C、小程序、Python等项目供你选择,真正体系化!
由于项目比较多,这里只是将部分目录截图出来,每个节点里面都包含素材文档、项目源码、讲解视频
如果你觉得这些内容对你有帮助,可以添加VX:vip1024c (备注项目大全获取)
监听
@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)]
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。