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