Redis(1)-用redis存储商品-用户关系

package com.lipeng;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SessionCallback;

public class UserSerivce {

	private RedisTemplate<String, Date> redisTemplate;
	HashOperations<String, String, Date> ho;

	public UserSerivce() {
		/**
		 * 加载配置文件
		 */
		ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext-redis.xml");
		redisTemplate = (RedisTemplate) ac.getBean("redisTemplate");
	}

	/**
	 * 用户喜欢一个商品
	 *
	 * @param uId
	 * @param pId
	 */
	public void addLove(String uId, String pId) {
		// 用户喜欢的商品增加一个
		final String uKey = getUKey(uId);
		final String uHashKey = pId + "";
		final String pKey = getPKey(pId);
		final String pHashKey = uId + "";
		final Date date = new Date();
		SessionCallback<Object> call = new SessionCallback<Object>() {

			public Object execute(RedisOperations ops) throws DataAccessException {
				// TODO Auto-generated method stub
				ops.multi();
				ho = ops.opsForHash();
				ho.put(uKey, uHashKey, date);
				ho.put(pKey, pHashKey, date);
				ops.exec();
				return null;
			}
		};
		redisTemplate.execute(call);
		// 用户喜欢数+1

	}

	/**
	 * 取消喜欢
	 *
	 * @param uId
	 * @param pId
	 */
	public void cannelLove(String uId, String pId) {
		final String uKey = getUKey(uId);
		final String pIdStr = pId;
		final String pKey = getPKey(pId);
		final String uIdStr = uId;
		SessionCallback<Object> call = new SessionCallback<Object>() {

			public Object execute(RedisOperations ops) throws DataAccessException {
				// TODO Auto-generated method stub
				ops.multi();
				ho = ops.opsForHash();
				ho.delete(uKey, pIdStr);
				ho.delete(pKey, uIdStr);
				ops.exec();
				return null;
			}
		};
		redisTemplate.execute(call);
	}

	/**
	 * 此用户是否喜欢此商品
	 *
	 * @param uId
	 * @param pId
	 */
	public boolean isLoved(String uId, String pId) {
		boolean re = false;
		final String uKey = getUKey(uId);
		final String uHashKey = pId + "";
		ho = redisTemplate.opsForHash();
		System.out.println(uKey + "  ,   " + uHashKey);
		re = ho.hasKey(uKey, uHashKey);
		return re;
	}

	/**
	 * 用户喜欢商品的数两
	 *
	 * @return
	 */
	public Long getLoveCountByUid(String uId) {
		final String uKey = getUKey(uId);
		long re = 0;
		ho = redisTemplate.opsForHash();
		re = ho.size(uKey);
		return re;
	}

	/**
	 * 商品的粉丝数
	 *
	 * @return
	 */
	public Long getLoveCountByPid(String pId) {
		final String pKey = getPKey(pId);
		long re = 0;
		ho = redisTemplate.opsForHash();
		re = ho.size(pKey);
		return re;
	}

	/**
	 * 删除商品
	 */

	public void delP(String pId) {
		// 删除商品的粉丝集合

		// 删除用户关注集合中的此商品

		final String pKey = getPKey(pId);
		final String pIdStr = pId + "";
		final Set<String> keys = redisTemplate.keys("uId:*:p");
		SessionCallback<Object> call = new SessionCallback<Object>() {

			public Object execute(RedisOperations ops) throws DataAccessException {
				// TODO Auto-generated method stub
				ho = ops.opsForHash();
				ops.delete(pKey);
				if (keys != null && keys.size() > 0) {
					for (String key : keys) {
						if (ho.hasKey(key, pIdStr)) {//如果此用户关注了该商品,则从关注列表中删除,这个操作不能放到multi中,
							//因为multi中的操作都是暂时放到命令队列中,到执行exec时统一提交,ho.hashKey()会返回null;
							System.out.println(pIdStr);
							ho.delete(key, pIdStr);
						}
					}
				}
				return null;
			}
		};

		redisTemplate.execute(call);
	}

	/**
	 * 获取商品的粉丝列表
	 *
	 * @param pId
	 * @param count
	 * @return
	 */
	public Map<String, Date> getUidsByPid(String pId, int count) {
		Map<String, Date> map = null;
		final String pKey = getPKey(pId);
		SessionCallback<Map<String, Date>> call = new SessionCallback<Map<String, Date>>() {

			public Map<String, Date> execute(RedisOperations ops) throws DataAccessException {
				// TODO Auto-generated method stub
				ops.multi();
				ho = ops.opsForHash();
				ops.exec();
				return (Map<String, Date>) ho.entries(pKey);
			}
		};
		map = redisTemplate.execute(call);
		return map;
	}

	/**
	 * 获取用户的喜欢列表
	 *
	 * @param uId
	 * @return
	 */
	private Map<String, Date> getPidsByUid(String uId) {
		Map<String, Date> map = null;
		final String uKey = getUKey(uId);
		SessionCallback<Map<String, Date>> call = new SessionCallback<Map<String, Date>>() {

			public Map<String, Date> execute(RedisOperations ops) throws DataAccessException {
				// TODO Auto-generated method stub
				ops.multi();
				ho = ops.opsForHash();
				ops.exec();
				return (Map<String, Date>) ho.entries(uKey);
			}
		};
		map = redisTemplate.execute(call);
		return map;
	}

	/**
	 * 获取用户关注的商品ids
	 *
	 * @param uId
	 * @return
	 */
	public List<String> getFocusPids(String uId) {
		return sortIds(this.getPidsByUid(uId));
	}

	/**
	 * 获取商品的粉丝IDS
	 *
	 * @param pId
	 * @return
	 */
	public List<String> getFansUids(String pId) {
		return sortIds(this.getUidsByPid(pId, 0));
	}

	public static String getUKey(String uId) {
		return "uId:" + uId + ":p";
	}

	public static String getUCountKey(String uId) {
		return "uId:" + uId + ":pCount";
	}

	public static String getPKey(String pId) {
		return "pId:" + pId + ":u";
	}

	public static String getPCountKey(String pId) {
		return "pId:" + pId + ":uCount";
	}

	/**
	 * 按时间进行排序
	 *
	 * @param map
	 * @return
	 */
	public List<String> sortIds(Map<String, Date> map) {
		List<Map.Entry<String, Date>> list = new LinkedList<Map.Entry<String, Date>>();
		list.addAll(map.entrySet());
		Collections.sort(list, new Comparator<Map.Entry<String, Date>>() {
			public int compare(Map.Entry<String, Date> date1, Map.Entry<String, Date> date2) {// 从高往低排序

				if (date1.getValue().getTime() < date2.getValue().getTime())
					return 1;
				if (date1.getValue().getTime() == date2.getValue().getTime())
					return 0;
				else
					return -1;
			}
		});
		List<String> ids = new ArrayList<String>();
		for (Iterator<Map.Entry<String, Date>> ite = list.iterator(); ite.hasNext();) {
			Map.Entry<String, Date> map1 = ite.next();
			System.out.println("key-value: " + map1.getKey() + "," + map1.getValue());
			ids.add(map1.getKey());
		}
		return ids;
	}

	/**
	 * 批量查询商品的粉丝
	 *
	 * @param pids
	 * @return key=pid value=fansCount
	 */
	public Map<String, Long> getFansCountByPids(List<String> pids) {
		Map<String, Long> map = new HashMap<String, Long>();

		ho = redisTemplate.opsForHash();
		for (String pId : pids) {
			String pidKey = this.getPKey(pId);
			Long size = ho.size(pidKey);
			map.put(pId, size);
		}
		return map;
	}
	/**
	 * 获取粉丝数最多的count个商品id
	 * @param count
	 * @return
	 */
	public Map<String,Long> getHot(int count)
	{
		Map<String,Long>map=new HashMap<String,Long>();
		ho=redisTemplate.opsForHash();
		Set<String> keys=redisTemplate.keys("pId:*:u");
		if(keys!=null)
		{
			for(String key:keys)
			{
				map.put(key, ho.size(key));
			}
		}
		return sortByCount(map,count);
	}

	public Map<String,Long>  sortByCount(Map<String,Long> map,int count)
	{
		Map<String,Long> re=new LinkedHashMap<String, Long>();
		List<Map.Entry<String, Long>> list = new ArrayList<Map.Entry<String, Long>>();
		list.addAll(map.entrySet());
		Collections.sort(list, new Comparator<Map.Entry<String, Long>>() {
			public int compare(Map.Entry<String, Long> date1, Map.Entry<String, Long> date2) {// 从高往低排序

				if (date1.getValue()< date2.getValue())
					return 1;
				if (date1.getValue() == date2.getValue())
					return 0;
				else
					return -1;
			}
		});
		for (Iterator<Map.Entry<String, Long>> ite = list.iterator(); ite.hasNext();) {
			Map.Entry<String, Long> map1 = ite.next();
			System.out.println("key-value: " + map1.getKey() + "," + map1.getValue());
			re.put(map1.getKey() , map1.getValue());
			if(re.size()==count)
			{
				return re;
			}
		}
		return re;
	}
	public static void main(String[] args) {
		UserSerivce us = new UserSerivce();

		 testAdds(us);

		// System.out.println(us.getLoveCountByPid(1));
		// System.out.println(us.getLoveCountByUid(3));
		// testCannelFocus(us);
		// testDel(us, uId, pId, list1, list2);
		// testGetFansCountByPids(us);
		//us.testMulti();
		Map<String, Long> map=us.getHot(2);
		System.out.println(map);
	}

	/**
	 * 测试取消关注
	 *
	 * @param us
	 */
	private static void testCannelFocus(UserSerivce us) {
		String uId = "0";
		String pId = "0";
		List<String> list1 = us.getFocusPids(uId);
		System.out.println("用户" + uId + " 的关注有" + list1);
		System.out.println("用户" + uId + "取消对商品" + pId + "的关注");
		us.cannelLove(uId, pId);
		List<String> list2 = us.getFocusPids(uId);
		System.out.println("用户" + uId + " 的关注有" + list2);
		System.out.println(us.getLoveCountByPid("0"));
	}

	/**
	 * 测试删除商品
	 *
	 * @param us
	 * @param uId
	 * @param pId
	 * @param list1
	 * @param list2
	 */
	private static void testDel(UserSerivce us, String uId, String pId, List<String> list1, List<String> list2) {
		System.out.println("商品" + pId + " 的粉丝有" + list1);
		System.out.println("用户" + uId + " 的关注有" + list2);
		System.out.println("现在删除商品" + pId);
		us.delP(pId);
		System.out.println("删完之后");
		List<String> list3 = us.getFansUids(pId);
		List<String> list4 = us.getFocusPids(uId);
		System.out.println("商品" + pId + " 的粉丝有" + list3);
		System.out.println("用户" + uId + " 的关注有" + list4);
	}

	/**
	 * 测试添加商品
	 *
	 * @param us
	 */
	private static void testAdds(UserSerivce us) {
		us.addLove("1", "1");
		us.addLove("2", "1");
		us.addLove("7", "3");
		us.addLove("8", "4");
		us.addLove("9", "4");
		us.addLove("1", "2");
		us.addLove("5", "3");
		us.addLove("4", "1");
	}

	/**
	 * 测试批量获取商品的粉丝数
	 *
	 * @param us
	 */
	public static void testGetFansCountByPids(UserSerivce us) {
		List<String> pids = new ArrayList<String>();
		pids.add("1");
		pids.add("2");
		pids.add("3");
		pids.add("4");
		Map<String, Long> map = us.getFansCountByPids(pids);
		System.out.println(map);
	}

	public void testMulti() {
		redisTemplate.watch("a");
		redisTemplate.multi();
		redisTemplate.exec();
		redisTemplate.unwatch();
	}
}

时间: 2024-12-17 14:41:47

Redis(1)-用redis存储商品-用户关系的相关文章

redis的数据持久化存储

redis的数据持久化存储 Redis是一个支持持久化的内存数据库,也就是说redis需要经常将内存中的数据同步到硬盘来保证持久化.Redis支持两种持久化方式: 一.snapshotting(快照)方式快照是默认的持久化方式.这种方式是将内存中数据以快照的方式写入到二进制文件中,默认的文件名为dump.rdb.我们可以配置redis在n秒内如果超过若干个key被修改就自动做快照持久保存. 在约87行,有默认的快照策略(指定在多长时间内,有多少次更新操作,就将数据同步到数据快照文件,可以多个条件

redis整理の走进redis世界

声明:原文摘自http://weibo.com/u/2446082491,谢谢他的分享! 在当前大型互联网应用以及提供云计算服务的时候,怎样保证系统在海量数据环境下的高性 能.高可靠性.高扩展性.高可用性.低成本成为迫切需要. 按照分布式CAP理论(Consistency. Availability.Tolerance to network Partitions[一致性.可用性.分区可溶性]这三 部分在任何系统架构实现时只可能同时满足其中二点,没法三者兼顾)来衡量,传统的关系数据库的 ACID(

深入剖析Redis系列: Redis集群模式搭建与原理详解

前言 在 Redis 3.0 之前,使用 哨兵(sentinel)机制来监控各个节点之间的状态.Redis Cluster 是 Redis 的 分布式解决方案,在 3.0 版本正式推出,有效地解决了 Redis 在 分布式 方面的需求.当遇到 单机内存.并发.流量 等瓶颈时,可以采用 Cluster 架构方案达到 负载均衡 的目的. 本文将从 集群方案.数据分布.搭建集群.节点通信.集群伸缩.请求路由.故障转移.集群运维 等几个方面介绍 Redis Cluster. 正文 1. Redis集群方

6.【Redis系列】Redis的高级应用-HyperLogLog

原文:6.[Redis系列]Redis的高级应用-HyperLogLog 老规矩还是先假设一个场景:比如京东的商品详情页,如果需要你来统计每天的UV数据,你会如何实现? 如果是PV就好办了,直接给每个网页增加一个计时器,每个网页增加一个日期,这样一进来incrby一次,最终可以计算出每天的统计所有的PV数据. 但是UV就不一样了,每一个用户进来多次每天也只能算一个UV.无论是登录用户还是未登录用户,都需要给一个唯一的ID来标识. 有可能你已经想到了通过set集合去重的功能,为每一个页面创建一个s

缓存系列之四:redis持久化与redis主从复制

一:redis 虽然是一个内存级别的缓存程序,即redis 是使用内存进行数据的缓存的,但是其可以将内存的数据按照一定的策略保存到硬盘上,从而实现数据持久保存的目的,redis支持两种不同方式的数据持久化保存机制,分别是RDB和AOF,具体实现如下: 1.1:redis数据持久化概括:redis 支持两种数据持久保存方式,分别是RDB和APFRDB可以设置在多长时间内有多少个key发生变化就执行RDB快照.AOF持久化是服务器记录和保存redis执行的所有命令,并在服务重启的时候重新执行全部的命

redis服务简介 && redis.conf配置文件详解

#一.redis服务简介 redis是一个key-value存储系统. 和Memcached类似,它支持存储的value类型相对更多(memcached不支持value类型,只支持key),包括string(字符串).list(链表).set(集合)和zset(有序集 合).这些数据类型都支持push/pop.add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的.在此基础上,redis 支持各种不同方式的排序.与memcached一样,为了保证效率,数据都是缓存在内存中

redis演练(5) redis持久化

何谓持久化,就是媳妇让你,持久一些. 说白了持久化:就是将内存中的数据保存到磁盘上的过程(数据库也算磁盘的特殊表现),以保证宕机或断电后,可以继续访问.java中常见的持久化框架,如Hibernate,ibatis,jdbc都是持久化实现方式的一种,当然普通文件保存功能也算. 拿memcached来说,memcached保存的信息,没有进行持久化,所以只能存活一个进程生命期,下次重新启动,数据全部丢失.这算memcached的一个缺点吧.redis提供了持久化支持,而且提供了2种持久化方案. <

Redis Essentials 读书笔记 - 第九章: Redis Cluster and Redis Sentinel (Collective Intelligence)

Chapter 9. Redis Cluster and Redis Sentinel (Collective Intelligence) 上一章介绍了复制,一个master可以对应一个或多个slave(replica), 在以下的情况下是够用的: 1. master有足够内存容纳所有key 2. 通过slave可以扩展读,解决网络吞吐量的问题 3. 允许停止master的维护窗口时间 4. 通过slave做数据冗余 但复制解决不了自动failover和自动resharding的问题,在以下的情

【redis】基于redis实现分布式并发锁

基于redis实现分布式并发锁(注解实现) 说明 前提, 应用服务是分布式或多服务, 而这些"多"有共同的"redis"; GitHub: https://github.com/vergilyn/SpringBootDemo 代码结构: 一.分布式并发锁的几种可行方案 (具体实现思路参考: 分布式锁的实现.如何用消息系统避免分布式事务?) 1.基于数据库 可以用数据库的行锁for update, 或专门新建一张锁控制表来实现. 过于依赖数据库, 且健壮性也不是特别好