zoukankan      html  css  js  c++  java
  • Redis常用技术

    Xml配置:

    <?xml version='1.0' encoding='UTF-8' ?>
    <!-- was: <?xml version="1.0" encoding="UTF-8"?> -->
    <beans xmlns="http://www.springframework.org/schema/beans"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
    	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
    	xmlns:context="http://www.springframework.org/schema/context"
    	xsi:schemaLocation="http://www.springframework.org/schema/beans 
    	   http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
           http://www.springframework.org/schema/aop 
           http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
           http://www.springframework.org/schema/tx 
           http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
           http://www.springframework.org/schema/context 
           http://www.springframework.org/schema/context/spring-context-4.0.xsd">
    	<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
    		<property name="maxIdle" value="50" />
    		<property name="maxTotal" value="100" />
    		<property name="maxWaitMillis" value="20000" />
    	</bean>
    
    	<bean id="stringRedisSerializer"
    		class="org.springframework.data.redis.serializer.StringRedisSerializer" />
    
    	<bean id="connectionFactory"
    		class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
    		<property name="hostName" value="localhost" />
    		<property name="port" value="6379" />
    		<property name="poolConfig" ref="poolConfig" />
    	</bean>
    
    	<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
    		<property name="connectionFactory" ref="connectionFactory" />
    		<property name="defaultSerializer" ref="stringRedisSerializer" />
    		<property name="keySerializer" ref="stringRedisSerializer" />
    		<property name="valueSerializer" ref="stringRedisSerializer" />
    	</bean>
    
    	<bean id="redisMsgListener"
    		class="com.ssm.chapter19.redis.listener.RedisMessageListener">
    		<property name="redisTemplate" ref="redisTemplate" />
    	</bean>
    
    	<bean id="topicContainer"
    		class="org.springframework.data.redis.listener.RedisMessageListenerContainer"
    		destroy-method="destroy">
    		<!--Redis连接工厂 -->
    		<property name="connectionFactory" ref="connectionFactory" />
    		<!--连接池,这里只要线程池生存,才能继续监听 -->
    		<property name="taskExecutor">
    			<bean
    				class="org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler">
    				<property name="poolSize" value="2" />
    			</bean>
    		</property>
    		<!--消息监听Map -->
    		<property name="messageListeners">
    			<map>
    				<!--配置监听者,key-ref和bean id定义一致 -->
    				<entry key-ref="redisMsgListener">
    					<!--监听类 -->
    					<bean class="org.springframework.data.redis.listener.ChannelTopic">
    						<constructor-arg value="chat" />
    					</bean>
    				</entry>
    			</map>
    		</property>
    	</bean>
    </beans>
    

      监听类:

    public class RedisMessageListener implements MessageListener {
    	
    	private RedisTemplate redisTemplate;
    
    	@Override
    	public void onMessage(Message message, byte[] bytes) {
    		// 获取消息
    		byte[] body = message.getBody();
    		// 使用值序列化器转换
    		String msgBody = (String) getRedisTemplate().getValueSerializer().deserialize(body);
    		System.err.println(msgBody);
    		// 获取channel
    		byte[] channel = message.getChannel();
    		// 使用字符串序列化器转换
    		String channelStr = (String) getRedisTemplate().getStringSerializer().deserialize(channel);
    		System.err.println(channelStr);
    		// 渠道名称转换
    		String bytesStr = new String(bytes);
    		System.err.println(bytesStr);
    	}
    
    	public RedisTemplate getRedisTemplate() {
    		return redisTemplate;
    	}
    
    	public void setRedisTemplate(RedisTemplate redisTemplate) {
    		this.redisTemplate = redisTemplate;
    	}
    }
    

      测试:

    public class Chapter19Main {
    
    	public static void main(String[] args) {
    		testTransaction();
    		testPipeline();
    		testJedisPipeline();
    		testPubSub();
    		testExpire();
    		testLuaScript();
    		testRedisScript();
    		testLuaFile();
    	}
    
    	public static void testTransaction() {
    		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
    		RedisTemplate redisTemplate = applicationContext.getBean(RedisTemplate.class);
    		SessionCallback callBack = (SessionCallback) (RedisOperations ops) -> {
    			ops.multi();
    			ops.boundValueOps("key1").set("value1");
    			// 注意由于命令只是进入队列,而没有被执行,所以此处采用get命令,而value却返回为null
    			String value = (String) ops.boundValueOps("key1").get();
    			System.out.println("事务执行过程中,命令入队列,而没有被执行,所以value为空:value=" + value);
    			// 此时list会保存之前进入队列的所有命令的结果
    			List list = ops.exec();// 执行事务
    			// 事务结束后,获取value1
    			value = (String) redisTemplate.opsForValue().get("key1");
    			return value;
    		};
    		// 执行Redis的命令
    		String value = (String) redisTemplate.execute(callBack);
    		System.out.println(value);
    	}
        public static void testPipeline() {
    		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
    		RedisTemplate redisTemplate = applicationContext.getBean(RedisTemplate.class);
    		// 使用Java8的Lambda表达式
    		SessionCallback callBack = (SessionCallback) (RedisOperations ops) -> {
    			for (int i = 0; i < 100; i++) {
    				int j = i + 1;
    				ops.boundValueOps("pipeline_key_" + j).set("pipeline_value_" + j);
    				ops.boundValueOps("pipeline_key_" + j).get();
    			}
    			return null;
    		};
    		long start = System.currentTimeMillis();
    		// 执行Redis的流水线命令
    		List resultList = redisTemplate.executePipelined(callBack);
    		long end = System.currentTimeMillis();
    		System.err.println(end - start);
    	}
    
    	private static JedisPool getPool() {
    		JedisPoolConfig poolCfg = new JedisPoolConfig();
    		// 最大空闲数
    		poolCfg.setMaxIdle(50);
    		// 最大连接数
    		poolCfg.setMaxTotal(100);
    		// 最大等待毫秒数
    		poolCfg.setMaxWaitMillis(20000);
    		// 使用配置创建连接池
    		JedisPool pool = new JedisPool(poolCfg, "localhost");
    		// 从连接池中获取单个连接
    		Jedis jedis = pool.getResource();
    		// 如果需密码
    		// jedis.auth("password");
    		return pool;
    	}
    
    	public static void testJedisPipeline() {
    		JedisPool pool = getPool();
    		Jedis jedis = pool.getResource();
    		long start = System.currentTimeMillis();
    		// 开启流水线
    		Pipeline pipeline = jedis.pipelined();
    		// 这里测试10万条的读写2个操作
    		for (int i = 0; i < 100; i++) {
    			int j = i + 1;
    			pipeline.set("pipeline_key_" + j, "pipeline_value_" + j);
    			pipeline.get("pipeline_key_" + j);
    		}
    		// pipeline.sync();//这里只执行同步,但是不返回结果
    		// pipeline.syncAndReturnAll();将返回执行过的命令返回的List列表结果
    		List result = pipeline.syncAndReturnAll();
    		long end = System.currentTimeMillis();
    		// 计算耗时
    		System.err.println("耗时:" + (end - start) + "毫秒");
    	}
    
    	public static void testPubSub() {
    		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
    		RedisTemplate redisTemplate = applicationContext.getBean(RedisTemplate.class);
    		String channel = "chat";
    		redisTemplate.convertAndSend(channel, "I am lazy!!");
    	}
    
    	public static void testExpire() {
    		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
    		RedisTemplate redisTemplate = applicationContext.getBean(RedisTemplate.class);
    		redisTemplate.execute((RedisOperations ops) -> {
    			ops.boundValueOps("key1").set("value1");
    			String keyValue = (String) ops.boundValueOps("key1").get();
    			Long expSecond = ops.getExpire("key1");
    			System.err.println(expSecond);
    			boolean b = false;
    			b = ops.expire("key1", 120L, TimeUnit.SECONDS);
    			b = ops.persist("key1");
    			Long l = 0L;
    			l = ops.getExpire("key1");
    			Long now = System.currentTimeMillis();
    			Date date = new Date();
    			date.setTime(now + 120000);
    			ops.expireAt("key", date);
    			return null;
    		});
    	}
    
    	public static void testLuaScript() {
    		// 如果是简单的对象,使用原来的封装会简易些
    		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
    		RedisTemplate redisTemplate = applicationContext.getBean(RedisTemplate.class);
    		// 如果是简单的操作,使用原来的Jedis会简易些
    		Jedis jedis = (Jedis) redisTemplate.getConnectionFactory().getConnection().getNativeConnection();
    		// 执行简单的脚本
    		String helloJava = (String) jedis.eval("return 'hello java'");
    		System.out.println(helloJava);
    		// 执行带参数的脚本
    		jedis.eval("redis.call('set',KEYS[1], ARGV[1])", 1, "lua-key", "lua-value");
    		String luaKey = (String) jedis.get("lua-key");
    		System.out.println(luaKey);
    		// 缓存脚本,返回sha1签名标识
    		String sha1 = jedis.scriptLoad("redis.call('set',KEYS[1], ARGV[1])");
    		// 通过标识执行脚本
    		jedis.evalsha(sha1, 1, new String[] { "sha-key", "sha-val" });
    		// 获取执行脚本后的数据
    		String shaVal = jedis.get("sha-key");
    		System.out.println(shaVal);
    		// 关闭连接
    		jedis.close();
    	}
    
    	public static void testRedisScript() {
    		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
    		RedisTemplate redisTemplate = applicationContext.getBean(RedisTemplate.class);
    		// 定义默认脚本封装类
    		DefaultRedisScript<Role> redisScript = new DefaultRedisScript<Role>();
    		// 设置脚本
    		redisScript.setScriptText("redis.call('set', KEYS[1], ARGV[1])  return redis.call('get', KEYS[1])");
    		// 定义操作的key列表
    		List<String> keyList = new ArrayList<String>();
    		keyList.add("role1");
    		// 需要序列化保存和读取的对象
    		Role role = new Role();
    		role.setId(1L);
    		role.setRoleName("role_name_1");
    		role.setNote("note_1");
    		// 获得标识字符串
    		String sha1 = redisScript.getSha1();
    		System.out.println(sha1);
    		// 设置返回结果类型,如果没有这句话,结果返回为空
    		redisScript.setResultType(Role.class);
    		// 定义序列化器
    		JdkSerializationRedisSerializer serializer = new JdkSerializationRedisSerializer();
    		// 执行脚本
    		// 第一个是RedisScript接口对象,第二个是参数序列化器
    		// 第三个是结果序列化器,第四个是Reids的key列表,最后是参数列表
    		Role obj = (Role) redisTemplate.execute(redisScript, serializer, serializer, keyList, role);
    		// 打印结果
    		System.out.println(obj);
    	}
    
    	public static void testLuaFile() {
    		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
    		RedisTemplate redisTemplate = applicationContext.getBean(RedisTemplate.class);
    		// 读入文件流
    		File file = new File("E:\study_fold\Java_EE_SSM\ssm\Chapter19\src\test.lua");
    		byte[] bytes = getFileToByte(file);
    		Jedis jedis = (Jedis) redisTemplate.getConnectionFactory().getConnection().getNativeConnection();
    		// 发送文件二进制给Redis,这样REdis就会返回sha1标识
    		byte[] sha1 = jedis.scriptLoad(bytes);
    		// 使用返回的标识执行,其中第二个参数2,表示使用2个键
    		// 而后面的字符串都转化为了二进制字节进行传输
    		Object obj = jedis.evalsha(sha1, 2, "key1".getBytes(), "key2".getBytes(), "2".getBytes(), "4".getBytes());
    		System.out.println(obj);
    	}
    
    	/**
    	 * 把文件转化为二进制数组
    	 * 
    	 * @param file
    	 *            文件
    	 * @return 二进制数组
    	 */
    	public static byte[] getFileToByte(File file) {
    		byte[] by = new byte[(int) file.length()];
    		try {
    			InputStream is = new FileInputStream(file);
    			ByteArrayOutputStream bytestream = new ByteArrayOutputStream();
    			byte[] bb = new byte[2048];
    			int ch;
    			ch = is.read(bb);
    			while (ch != -1) {
    				bytestream.write(bb, 0, ch);
    				ch = is.read(bb);
    			}
    			by = bytestream.toByteArray();
    		} catch (Exception ex) {
    			ex.printStackTrace();
    		}
    		return by;
    	}
    }
    

      输出:

    事务执行过程中,命令入队列,而没有被执行,所以value为空:value=null
    value1

    23


    耗时:13毫秒

    I am lazy!!
    chat
    chat
    I am lazy!!
    chat
    chat
    I am lazy!!
    chat
    chat

    -1

    hello java
    lua-value
    sha-val

    731429de653665577edb661a6741c4083e103b77
    com.ssm.chapter19.redis.pojo.Role@59474f18

    2

    对于高并发的需求,可以用主从同步同步,结合哨兵模式解决,参考:

    https://blog.csdn.net/shenlf_bk/article/details/79095469

    https://www.cnblogs.com/leirayen/p/8183111.html

  • 相关阅读:
    CDQ分治
    K-th Number POJ
    A * B Problem Plus HDU
    Prime Test POJ
    数据结构
    FFT
    mysql查询出相同数据出现的次数,统计相同值的数量
    Laravel 清空配置缓存
    php7 数据导出Excel office 2011中文乱码问题
    PHP file_put_contents函数数据导出csv文件,屏幕字符串逗号分隔符
  • 原文地址:https://www.cnblogs.com/daxiong225/p/9978275.html
Copyright © 2011-2022 走看看