Redis高级数据类型

image.png
测试HyperLogLog的使用

  1. //统计20万个数据的独立总数
  2. @Test
  3. public void testHyperLogLog(){
  4. String redisKey = "test:hll:01";
  5. for(int i = 1; i <= 100000; i++){
  6. redisTemplate.opsForHyperLogLog().add(redisKey,i);
  7. }
  8. for(int i = 1; i <= 100000; i++){
  9. int r = (int) (Math.random() * 100000 + 1);
  10. redisTemplate.opsForHyperLogLog().add(redisKey,r);
  11. }
  12. Long size = redisTemplate.opsForHyperLogLog().size(redisKey);
  13. System.out.println(size);
  14. }
  15. //size = 99553
  1. //将三组数据合并,再统计合并重复数据的独立总数
  2. @Test
  3. public void testHyperLoglogUnion(){
  4. String redisKey2 = "test:hll:02";
  5. for (int i = 1; i <= 10000; i++) {
  6. redisTemplate.opsForHyperLogLog().add(redisKey2,i);
  7. }
  8. String redisKey3 = "test:hll:03";
  9. for (int i = 1; i <= 15000; i++) {
  10. redisTemplate.opsForHyperLogLog().add(redisKey3,i);
  11. }
  12. String redisKey4 = "test:hll:04";
  13. for(int i = 1; i <= 20000; i++){
  14. redisTemplate.opsForHyperLogLog().add(redisKey4,i);
  15. }
  16. String redisKeyUnion = "test:hll:union";
  17. Long size = redisTemplate.opsForHyperLogLog().union(redisKeyUnion,redisKey2,redisKey3,redisKey4);
  18. System.out.println(size);
  19. }

测试Bitmap的使用

  1. //统计一组数据的布尔值
  2. @Test
  3. public void testBitMap(){
  4. String redisKey = "test:bm:01";
  5. //记录
  6. redisTemplate.opsForValue().setBit(redisKey,1,true);
  7. redisTemplate.opsForValue().setBit(redisKey,4,true);
  8. redisTemplate.opsForValue().setBit(redisKey,7,true);
  9. //查询
  10. System.out.println(redisTemplate.opsForValue().getBit(redisKey,0));
  11. System.out.println(redisTemplate.opsForValue().getBit(redisKey,1));
  12. System.out.println(redisTemplate.opsForValue().getBit(redisKey,2));
  13. //统计
  14. Object obj = redisTemplate.execute(new RedisCallback() {
  15. @Override
  16. public Object doInRedis(RedisConnection redisConnection) throws DataAccessException {
  17. return redisConnection.bitCount(redisKey.getBytes());
  18. }
  19. });
  20. System.out.println(obj);
  21. }

网站数据统计

image.png
DataService

  1. public class DataService {
  2. @Autowired
  3. private RedisTemplate redisTemplate;
  4. private SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
  5. public void recordUV(String ip){
  6. String redisKey = RedisKeyUtil.getUVKey(df.format(new Date()));
  7. redisTemplate.opsForHyperLogLog().add(redisKey,ip);
  8. }
  9. public long calculateUV(Date start, Date end){
  10. if(start == null || end == null){
  11. throw new IllegalArgumentException("参数不能为空");
  12. }
  13. //整理该日期内的key
  14. List<String> KeyList = new ArrayList<>();
  15. Calendar calendar = Calendar.getInstance();
  16. calendar.setTime(start);
  17. while (!calendar.getTime().after(end)){
  18. String key = RedisKeyUtil.getUVKey(df.format(calendar.getTime()));
  19. KeyList.add(key);
  20. calendar.add(Calendar.DATE,1);
  21. }
  22. //合并这些天的 UV
  23. String redisKey = RedisKeyUtil.getUVKey(df.format(start), df.format(end));
  24. redisTemplate.opsForHyperLogLog().union(redisKey,KeyList.toArray());
  25. // 返回统计结果
  26. return redisTemplate.opsForHyperLogLog().size(redisKey);
  27. }
  28. /**
  29. * 将指定的 IP 计入当天的 DAU
  30. * @param userId
  31. */
  32. public void recordDAU(int userId) {
  33. String redisKey = RedisKeyUtil.getDAUKey(df.format(new Date()));
  34. redisTemplate.opsForValue().setBit(redisKey, userId, true);
  35. }
  36. /**
  37. * 统计指定日期范围内的 DAU
  38. * @param start
  39. * @param end
  40. * @return
  41. */
  42. public long calculateDAU(Date start, Date end) {
  43. if (start == null || end == null) {
  44. throw new IllegalArgumentException("参数不能为空");
  45. }
  46. // 整理该日期范围内的 key
  47. List<byte[]> keyList = new ArrayList<>();
  48. Calendar calendar = Calendar.getInstance();
  49. calendar.setTime(start);
  50. while (!calendar.getTime().after(end)) {
  51. String key = RedisKeyUtil.getDAUKey(df.format(calendar.getTime()));
  52. keyList.add(key.getBytes());
  53. calendar.add(Calendar.DATE, 1); // 加1天
  54. }
  55. // 进行 or 运算
  56. return (long) redisTemplate.execute(new RedisCallback() {
  57. @Override
  58. public Object doInRedis(RedisConnection redisConnection) throws DataAccessException {
  59. String redisKey = RedisKeyUtil.getDAUKey(df.format(start), df.format(end));
  60. redisConnection.bitOp(RedisStringCommands.BitOperation.OR,
  61. redisKey.getBytes(), keyList.toArray(new byte[0][0]));
  62. return redisConnection.bitCount(redisKey.getBytes());
  63. }
  64. });
  65. }
  66. }

DataController

  1. @Controller
  2. public class DataController implements CommunityConstant {
  3. @Autowired
  4. private DataService dataService;
  5. /**
  6. * 进入统计页面
  7. * @return
  8. */
  9. @RequestMapping(value = "/data", method = {RequestMethod.GET,RequestMethod.POST})
  10. public String getDataPage(){
  11. return "/site/admin/data";
  12. }
  13. /**
  14. * 统计网站 uv(独立用户访问)
  15. * @param start
  16. * @param end
  17. * @param model
  18. * @return
  19. */
  20. @PostMapping("/data/uv")
  21. public String getUV(@DateTimeFormat(pattern = "yy-MM-dd")Date start,
  22. @DateTimeFormat(pattern = "yy-MM-dd")Date end,
  23. Model model){
  24. long uv = dataService.calculateUV(start, end);
  25. model.addAttribute("uvResult",uv);
  26. model.addAttribute("uvStartDate",start);
  27. model.addAttribute("uvEndDate",end);
  28. return "forward:/data";
  29. }
  30. /**
  31. * 统计网站 dau(日活跃用户数量)
  32. * @param start
  33. * @param end
  34. * @param model
  35. * @return
  36. */
  37. @PostMapping("/data/dau")
  38. public String getDAU(@DateTimeFormat(pattern = "yyyy-MM-dd") Date start,
  39. @DateTimeFormat(pattern = "yyyy-MM-dd") Date end,
  40. Model model){
  41. long dau = dataService.calculateDAU(start,end);
  42. model.addAttribute("dauResult",dau);
  43. model.addAttribute("dauStartDAte",start);
  44. model.addAttribute("dauEndDate",end);
  45. return "forward:/data";
  46. }
  47. }