redis配置及和spring的各种结合
博客专区 > whaon 的博客 > 博客详情
redis配置及和spring的各种结合
whaon 发表于1年前
redis配置及和spring的各种结合
  • 发表于 1年前
  • 阅读 919
  • 收藏 10
  • 点赞 1
  • 评论 0

腾讯云 技术升级10大核心产品年终让利>>>   

下载

wget http://download.redis.io/releases/redis-3.2.1.tar.gz

编译安装运行

make && make install 如果出错使用 make MALLOC=libc && make install 安装成功后,会自动把一些可执行文件复制到环境变量/usr/local/bin/下

redis-benchmark
redis-check-aof
redis-check-rdb
redis-cli
redis-sentinel
redis-server

redis根目录下有2个重要的配置文件

  1. redis.conf #redis本身的配置文件
  2. sentinel.conf #容灾部署的配置文件(哨兵)

redis是可以在客户端执行一些配置命令,并且是可以反写入配置文件的,所以有时候发现配置文件默默的被修改了千万不要惊讶

可以直接使用这2个配置文件,我的习惯是复制这2个文件到/etc/目录下,然后启动的时候指定/etc/下的配置文件

配置redis.conf

bind 127.0.0.1 #这一行注释掉,这样其他机器才可以访问
port 6379 #修改端口号
daemonize yes #改为后台运行
logfile ""  #指定日志文件的路径
databases 16 #数据库的数目,可以对比mysql来理解,默认是16,不同db的key不会冲突,可以在客户端redis-cli中用select 8来切换db
dbfilename "dump.rdb" #RDB持久化的文件名称
requirepass "foobared" #需要设置复杂一点的密码
maxmemory 3gb #设置给redis使用的最大内存
maxmemory-policy volatile-lru #最大内存策略
hash-max-ziplist-entries 512 #以下都是一些内存优化策略
hash-max-ziplist-value 64
list-max-ziplist-size -2
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64

# 禁用高危的命令
rename-command FLUSHALL ""
rename-command CONFIG   ""
rename-command EVAL     ""

运行redis-server /etc/redis.conf

持久化

支持2种,RDB和AOF,默认开启RDB,关闭AOF,根据实际情况进行配置 RDB建议一定开启,开启后,redis内存中的数据会保存到dump.rdb,并且所有的db共享,可以对该文件定期备份,redis重启后,会读取dump.rdb里面的数据到内存 手动执行save命令可以立即把内存中的数据保存到db中

主备

2台redis,一台master,一台slave,只需在slave上加入如下配置

slaveof <masterip> <masterport>
masterauth foobared
slave-read-only yes #建议开启

这样在master上操作的数据就会同步到slave,在slave上修改的数据不会同步到master,并且slave重启后,会先执行flushall,然后重新从master同步,从以下日志也可以看粗来

28884:S 14 Jul 01:52:48.269 * Full resync from master: 13a3a2cb882f2b18e8d689b19ab5db711301ca2f:4682895
28884:S 14 Jul 01:52:48.438 * MASTER <-> SLAVE sync: receiving 167 bytes from master
28884:S 14 Jul 01:52:48.439 * MASTER <-> SLAVE sync: Flushing old data
28884:S 14 Jul 01:52:48.439 * MASTER <-> SLAVE sync: Loading DB in memory
28884:S 14 Jul 01:52:48.439 * MASTER <-> SLAVE sync: Finished with success

容灾

  1. 可以用传统的keepalived
  2. 使用zookeeper,需要在redis启动时操作zookeeper
  3. 使用redis自带的sentinel机智,推荐,安装完redis后就会有redis-sentinel这个可执行文件,一般会在运行redis的机器上都运行sentinel
配置sentinel.conf
daemonize yes #也需要加上
port 7031 #修改端口
protected-mode no #这个必须加上,否则其他机器连不上
sentinel monitor <master-name> <ip> <redis-port> <quorum>
sentinel down-after-milliseconds <master-name> <milliseconds>
sentinel failover-timeout mymaster 10000
sentinel parallel-syncs <master-name> <numslaves>
sentinel auth-pass <master-name> <password>

运行redis-sentinel /etc/sentinel.conf 执行redis-cli -p sentinel-port,接着执行 SENTINEL masters #来查看master的信息,也可以执行以下命令 SENTINEL get-master-addr-by-name mymaster #jedis就是通过这种方式来找到slave的 这样配置好后,如果master挂了,过了一小段时间后,slave会提升为master,并且之前的master如果恢复后,会自己变成slave,配置文件redis.conf也会被修改 **注意:**sentinel本身是没有密码的,只要配置了protected-mode no客户端就可以随意访问,但是master是需要密码的。上面的配置sentinel auth-pass &lt;master-name&gt; &lt;password&gt;不是sentinel的密码,而是发生主备切换时sentinel修改本地redis.conf配置时所需要的密码。

使用jedis来操作redis

可以使用纯jedis来操作

maven

<dependency>  
      <groupId>redis.clients</groupId>  
      <artifactId>jedis</artifactId>  
      <version>2.8.1</version>  
</dependency>

会自动引入commons-pool

和spring结合(不使用spring-data-redis,不使用RedisTemplate)

1.直接使用pool

<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
		<property name="maxTotal" value="50" />
		<property name="maxIdle" value="10" />
		<property name="minIdle" value="0" />
</bean>
<bean id="jedisPool" class="redis.clients.jedis.JedisPool" destroy-method="destroy">
		<constructor-arg name="poolConfig" ref="jedisPoolConfig"></constructor-arg>
		<constructor-arg name="host" value="172.16.154.233"></constructor-arg>
		<constructor-arg name="port" value="6379"></constructor-arg>
		<constructor-arg name="timeout" value="30000"></constructor-arg>
		<constructor-arg name="password" value="foobared"></constructor-arg>
</bean>

2.使用sentinel pool

<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
		<property name="maxTotal" value="50" />
		<property name="maxIdle" value="10" />
		<property name="minIdle" value="0" />
</bean>
<bean id="jedisPool" class="redis.clients.jedis.JedisSentinelPool">
		<constructor-arg index="0" value="mymaster" />
		<constructor-arg index="1">
			<set>
				<value>172.16.154.232:7031</value>
				<value>172.16.154.233:7031</value>
			</set>
		</constructor-arg>
		<constructor-arg index="2" ref="jedisPoolConfig" />
		<constructor-arg index="3" value="600000" />
		<constructor-arg index="4" value="foobared" />
	</bean>

这样,取得jedisPool这个bean,然后调用getResource()方法即可获得Jedis这个操作类

和spring结合(使用spring-data-redis,使用RedisTemplate)

maven

<dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-redis</artifactId>
        <version>1.7.2.RELEASE</version>
</dependency>

配置

	<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
		<property name="maxTotal" value="50" />
		<property name="maxIdle" value="10" />
		<property name="minIdle" value="0" />
	</bean>
	<bean id="sentinelConfig" class="org.springframework.data.redis.connection.RedisSentinelConfiguration">
		<constructor-arg name="master" value="mymaster"></constructor-arg>
		<constructor-arg name="sentinelHostAndPorts">
			<set>
			    <value>172.16.154.232:7031</value>
			    <value>172.16.154.233:7031</value>
			</set>
		</constructor-arg>
	</bean>
	<bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
		<constructor-arg name="sentinelConfig" ref="sentinelConfig" />
		<constructor-arg name="poolConfig" ref="jedisPoolConfig" />
		<property name="password" value="foobared"></property>
	</bean>
	<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
		<property name="connectionFactory" ref="connectionFactory" />
	</bean>
	<bean id="stringRedisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate">
		<property name="connectionFactory" ref="connectionFactory" />
	</bean>

注意配置了2个template,RedisTemplate和StringRedisTemplate RedisTemplate默认使用了JdkSerializationRedisSerializer,是通过ObjectInputStream和ObjectOutputStream来实现序列化,而且本身的操作不是很方便,虽然实现了模板模式,但是很多都是通过执行execute,自己仍然需要实现匿名内部类,我们可通过执行opsForXXX来获得一些比较方便的操作类来进行操作,最典型的就是执行opsForValue()来获得ValueOperations,该类提供了一些比较方便的API

public interface ValueOperations<K, V> {

	void set(K key, V value);

	/**
	 * Set {[[[[[@code](http://my.oschina.net/codeo)](http://my.oschina.net/codeo)](http://my.oschina.net/codeo)](http://my.oschina.net/codeo)](http://my.oschina.net/codeo) key} to hold the string {[[[[[@code](http://my.oschina.net/codeo)](http://my.oschina.net/codeo)](http://my.oschina.net/codeo)](http://my.oschina.net/codeo)](http://my.oschina.net/codeo) value} until {[[[[[@code](http://my.oschina.net/codeo)](http://my.oschina.net/codeo)](http://my.oschina.net/codeo)](http://my.oschina.net/codeo)](http://my.oschina.net/codeo) timeout}.
	 * 
	 * [[[[[@param](http://my.oschina.net/u/2303379)](http://my.oschina.net/u/2303379)](http://my.oschina.net/u/2303379)](http://my.oschina.net/u/2303379)](http://my.oschina.net/u/2303379) key
	 * [[[[[@param](http://my.oschina.net/u/2303379)](http://my.oschina.net/u/2303379)](http://my.oschina.net/u/2303379)](http://my.oschina.net/u/2303379)](http://my.oschina.net/u/2303379) value
	 * @param timeout
	 * @param units
	 * @see http://redis.io/commands/set
	 */
	void set(K key, V value, long timeout, TimeUnit unit);

	Boolean setIfAbsent(K key, V value);

	void multiSet(Map<? extends K, ? extends V> m);

	Boolean multiSetIfAbsent(Map<? extends K, ? extends V> m);

	V get(Object key);

	V getAndSet(K key, V value);

	List<V> multiGet(Collection<K> keys);

	Long increment(K key, long delta);

	Double increment(K key, double delta);

	Integer append(K key, String value);

	String get(K key, long start, long end);

	void set(K key, V value, long offset);

	Long size(K key);

	RedisOperations<K, V> getOperations();
	
	/**
	 * @since 1.5
	 * @param key
	 * @param offset
	 * @param value
	 * @return
	 */
	Boolean setBit(K key, long offset, boolean value);
	
	/**
	 * @since 1.5
	 * @param key
	 * @param offset
	 * @return
	 */
	Boolean getBit(K key, long offset);
	
}

但是由于默认是使用JdkSerializationRedisSerializer,所以你通过set方法后,在redis-cli中会看不到你想要的结果,比如执行了template.opsForValue().set("r", "r"),但是通过keys *看到的结果是"\xac\xed\x00\x05t\x00\x01r",在redis-cli中执行get r会返回(nil),需要执行get "\xac\xed\x00\x05t\x00\x01r"才能得到结果,并且是"\xac\xed\x00\x05t\x00\x01r",但是通过RedisTemplate是可以正常访问的template.opsForValue().get("r"),因为它会帮你进行序列化和反序列化

再看StringRedisTemplate,StringRedisTemplate是继承RedisTemplate,无非是使用StringRedisSerializer,其他和RedisTemplate一样,该Serializer是使用String类来进行序列化的,和jedis原生的一样,代码如下:

public class StringRedisSerializer implements RedisSerializer<String> {

	private final Charset charset;

	public StringRedisSerializer() {
		this(Charset.forName("UTF8"));
	}

	public StringRedisSerializer(Charset charset) {
		Assert.notNull(charset);
		this.charset = charset;
	}

	public String deserialize(byte[] bytes) {
		return (bytes == null ? null : new String(bytes, charset));
	}

	public byte[] serialize(String string) {
		return (string == null ? null : string.getBytes(charset));
	}
}

使用StringRedisTemplate后,再使用上述的template.opsForValue().set("r", "r")机会得到你想要的比较正常的结果了

spring还提供了一些其他的Serializer,部分如下:

StringRedisSerializer
OxmSerializer
Jackson2JsonRedisSerializer

-------------------------------------------------分割线2017年8月15日17:18:51-------------------------------------------------
最先版本为4.0.1 wget http://download.redis.io/releases/redis-4.0.1.tar.gz

标签: java redis spring
共有 人打赏支持
whaon
粉丝 42
博文 36
码字总数 31073
×
whaon
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: