您的位置:首页 > 数据库 > Redis

redis配置及和spring的各种结合

2016-07-14 11:00 253 查看

下载

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

编译安装运行

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个重要的配置文件

redis.conf #redis本身的配置文件

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

容灾

可以用传统的keepalived

使用zookeeper,需要在redis启动时操作zookeeper

使用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 <master-name> <password>
不是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