#redis ==>数据库,缓存,消息中间件#五种数据类型strings / hashs / lists / sets / sorted setsps -ef|grep redis #查看redis进程(在命令行下)#启动redis,首先要知道redis-server位置,还要知道redis.conf位置**使用 locate redis-server 和 locate redis.conf **#接着使用下面指令/usr/local/bin/redis-server /www/server/redis/redis.confnetstat -nplt #可以查看是否启动成功#连接edisredis-cli -p 6379 #(下面语句在redis下)set key xxxget keykeys * #所有keyshutdown --> exit #退出redis#测试redis-benchmarkredis-benchmark -h localhost -p 6379 -c 100 -n 100000#共16个数据库select * #切换数据库dbsize #查看数据库大小flushdb #清空当前库flushall #清空所有数据库exists name #判断name是否存在move name 1 #移动name到数据库1del name #删除keyexpire name 10 #十秒后过期这时候使用ttl #name查看他的时间type name #查看name类型append name "hello" #在name后追加hellostrlen name #看name长度
set views 0incr views #views加1decr views #views减1incrby views 10 #增长10decrby views 10 #减10
getrange name 0 3 #截取字符串[0,3]getrange name 0 -1 #截取全部字符串
#替换 name=abcdsetrange name 1 xx #从1位开始替换两位 变成 axxdsetex (set with expire)#设置过期时间setnx (set if not exist)#不存在再设置
mset k1 v1 k2 v2 k3 v3 #批量设置msetnx k1 v1 k2 v2 #接上一条指令,会设置失败,因为已经存在,要么都成功,要么都失败
set user:1 {name:zhangsan,age:12}mset user:1:name zhangsan user:2:age 2
getset name xxx # 先get再set,不存在会返回nil但是也会创建
所有list命令l开头
lpush是将一个或多个值插入到头部 (leftpush)lpush list onelpush list twolpush list threelrange list 0 -1 #拿全部值lrange list 0 1 #拿到 three 和 two 栈,先进后出rpush #是将一个或多个值插入到尾部lpop #头部移除rpop #尾部移除lindex list 1 #通过下标获取值llen list #查看长度lrem list 1 one #移除指定的值 one一次lrem list 2 three #移除指定值three 两次######################################################
trim #修剪ltrim list 1 2 #从头部 1, 2 位置截取剩下2个(如 lpush list a b c d e,(e为头部)ltrim list 1 2后lrange list 0 -1 结果为 d c )rtrim#####################################################rpoolpush list newlist #移除list最后一个元素并添加到新列表lset list 1 item #在list指定下标赋值linsert list before "b" "z" #b 前面插入 zlinsert list after "b" "z" #b 后面插入 z
set 无序的里面的值不允许重复sadd myset "hello"sadd myset "hello1"sadd myset "hello2"smembers myset #查看sismember myset hello #返回1 已存在 无法插入sismember myset hello4 #返回0 不存在,可以加入scard myset #获取myset元素个数srem myset hello #移除set中的元素helloset 抽取随机元素srandmember mysetspop 随机弹出元素smove myset myset2 "hello"##################################################sdiff set1 set2 #差集sinter set1 set2 #交集,共同好友sunion set1 set2 #并集
hash(哈希) Map集合hset myhash field1 ahget myhash field1 # 获取字段值hmset myhash field1 a field2 b #同时设置多个hashhgetall myhash #获取全部hashhexists myhash field1 #判断field1是否存在hsetnx myhash field1 hello #不存在才创建hincrby myhash field1 1 #给field+1
zadd myset 1 onezadd myset 2 twozadd myset 3 three可以排序,比如工资zadd salary 2500 xiaozadd salary 3000 zhangzadd salary 500 dazrevrange myset 0 -1 倒序zrangebyscore salary -inf +inf (负无穷到正无穷)zrevrangebyscore myset 10000 100(倒序)zcount myset 1 10 获取1到10间的成员数量
推算两地距离,附近人
geoadd china:city 纬度 经度 城市geoadd china:city 116.397128 39.916527 beijinggeoadd china:city 121.48941 31.40527 shanghaigeoadd china:city 106.54041 29.40268 chongqinggeoadd china:city 106.54041 29.40268 chongqing#java可以批量导入地理数据geopos china:city beijing #查询地理位置两人之间的距离geodist m:米km:千米mi:英里ft:英尺geodist china:city beijing chongqing km #km设置单位附近的人,先获得定位,通过半径查询.georadius georadius china:city 110 30 1000 km #查询经度110 纬度30范围1000km之内的城市georadius china:city 110 30 1000 km withdist#显示指定位置指定距离内城市与其距离georadius china:city 110 30 1000 km withcoord#显示位置的指定范围的城市的定位信息georadius china:city 110 30 1000 km withdist withcoord count 2 #筛选出两个指定的结果,包含距离和定位信息georadiusbymember china:city beijing 1500 km#找出指定元素范围内的元素名称geahash字符串属性,将二维经纬度转为一维的字符串geohash china:city beijing "wx4g0dtf9e0" `底层是zset,所以可以通过zet进行操作,比如移除元素等` zrange china:city 0 -1 #查询所有元素 zrem china:city beijing #移除北京这个元素
基数:不重复的元素
A{1,3,5,6,5}==>A{1,3,5,6}
简介
网站的UV(一个人访问多次算一个人)
优点:只需要12kb内存.2^64个元素,错误率低 0.81%,统计UV合适
pfadd my a b c d e c d s c v d a s a #添加元素pfcount my #统计不同元素数量 7pfadd me c d c s a x s c z #添加第二组pfmerge new my me #合并my和me成new.pfcount new #统计出new的基数数量pfadd x 逐个添加时,重复的会添加失败
位存储
统计用户信息,活跃,不活跃,登录,未登录,打卡.只有两个状态就可以使用
127.0.0.1:6379> setbit sign 0 1(integer) 0127.0.0.1:6379> setbit sign 1 0(integer) 0127.0.0.1:6379> setbit sign 2 1(integer) 0127.0.0.1:6379> setbit sign 3 1(integer) 0127.0.0.1:6379> setbit sign 4 1(integer) 0127.0.0.1:6379> setbit sign 5 0(integer) 0127.0.0.1:6379> setbit sign 6 1(integer) 0七天sign的设置情况查看某一天的bit值getbit sign 50#统计这周打卡记录bitcount sign
redis单条命令保证原子性,
但是事务不保证原子性
redis 没有隔离级别的概念
开启事务
命令入列
执行事务(exec)
乐观锁
监视器watch
127.0.0.1:6379> multi #开启事务OK127.0.0.1:6379> set k1 v1 #命令入队QUEUED127.0.0.1:6379> set k2 v2 #命令入队QUEUED127.0.0.1:6379> set k3 v3 #命令入队QUEUED127.0.0.1:6379> get k1 #命令入队QUEUED127.0.0.1:6379> exec #执行1) OK2) OK3) OK4) "v1"
放弃事务: discard
编译型异常,所有代码都不会执行
运行时异常,错误命令异常,其他命令正常执行
悲观锁:
乐观锁:
redis监控测试
127.0.0.1:6379> set money 100OK127.0.0.1:6379> set out 0OK127.0.0.1:6379> watch moneyOK127.0.0.1:6379> multiOK127.0.0.1:6379> decrby money 20QUEUED127.0.0.1:6379> incrby out 20QUEUED127.0.0.1:6379> exec1) (integer) 802) (integer) 20#使用watch可以当乐观锁操作,watch后如果冲突会执行失败失败后,再watch再开启事务再命令入列执行
Java操作redis的中间件
新建java springboot项目,导入jedis,fastjson
@Test void test() {
Jedis jedis = new Jedis("127.0.0.1", 6379); jedis.set("name", "fuckyou"); System.out.println("清空数据: "+jedis . flushDB()); System.out.println("判断某个键是否存在: " + jedis.exists("username")); System.out.println("新增< 'username', ' user'>的键值对: " + jedis.set("username", "ku")); System.out.println("新增的键值对: " + jedis.set("password", "pas")); System. out. print("系统中所有的键如下: "); Set keys = jedis. keys( "*"); System. out . println(keys); System . out . println( "删除键password: "+jedis . del( "password")); System. out . println( "判断键password是否存在: "+jedis. exists( "password")); System . out . println( "查看键username所存储的值的类型: "+jedis. type( "username")); System. out . println( "随机返回key空间的一个: "+jedis . randomKey()); System . out . println("重命名 "+jedis . rename( "username", "name" )); System . out. println( "取出改后的name: "+jedis. get("name")); System. out. println("按索引查询: "+jedis. select( 0)); System. out . println( "删除当前选择数据库中的所有key: "+jedis . flushDB()); System. out . println("返回当前数据库中key的数目: "+jedis. dbSize()); System. out . println("删除所有数据库中的所有key: "+jedis.flushAll());}
@Test void test() {
Jedis jedis = new Jedis("127.0.0.1", 6379); Transaction multi = jedis.multi(); JSONObject object = new JSONObject(); object.put("k1", "v1"); object.put("k2", "v2"); String toJSONString = object.toJSONString(); try {
multi.set("user1", toJSONString); multi.exec();//执行事务 } catch (Exception e) {
multi.discard();//放弃事务 e.printStackTrace(); }finally {
System.out.println(jedis.get("user1")); jedis.close();//最后关闭连接 }}
pom.xml引入包 spring-boot-starter-data-redis
新建项目界面nosql中的第一个redis
jedis已经不使用了,直连不安全,BIO模式
用的lettuce,采用netty,多线程中进行共享,减少线程数据.NIO模式
即可知道redis相关配置
@Configuration(proxyBeanMethods = false)@ConditionalOnClass(RedisOperations.class)@EnableConfigurationProperties(RedisProperties.class)@Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })public class RedisAutoConfiguration {
@Bean @ConditionalOnMissingBean(name = "redisTemplate") public RedisTemplate
#spring.redis.host=127.0.0.1#spring.redis.port=6379#spring.redis.lettuce.pool.max-active=8#等等..默认lettuce.基本不需要自己配置
@SpringBootTestclass DemoApplicationTests {
@Autowired private RedisTemplate redisTemplate; @Test void contextLoads() {
} @Test void Test() {
redisTemplate.opsForValue().set("k1", "v1"); redisTemplate.opsForList().leftPush("k2", "v2"); List k2 = redisTemplate.opsForList().range("k2", 0, -1); System.out.println(k2); redisTemplate.opsForSet(); redisTemplate.opsForHash(); redisTemplate.opsForZSet(); redisTemplate.opsForGeo(); redisTemplate.opsForHyperLogLog(); } }
//关键代码: @Autowiredprivate RedisTemplate redisTemplate;//接着使用即可redisTemplate.opsForValue().set("k1", "v1");//操作stringredisTemplate.opsForList().leftPush("k2", "v2");//操作listList k2 = redisTemplate.opsForList().range("k2", 0, -1);System.out.println(k2);redisTemplate.opsForSet();//操作setredisTemplate.opsForHash();//操作hashredisTemplate.opsForZSet();//操作zsetredisTemplate.opsForGeo();//操作georedisTemplate.opsForHyperLogLog();//操作基数
删除数据需要另外获取连接
RedisConnection connection = redisTemplate.getConnectionFactory().getConnection(); connection.flushAll();//删除所有数据 connection.flushDb();//删除数据
如果不进行对象序列号,会报错,需要自己执行序列号操作 ` class User`@Component//方便直接调用@Data@AllArgsConstructor@NoArgsConstructorpublic class User {
private String name; private Integer age; }` Test ` @Test void Test() throws JsonProcessingException {
User user = new User("哈哈", 10); String s = new ObjectMapper().writeValueAsString(user);//不序列号不行,所有可以在pojo里面对象直接序列号 redisTemplate.opsForValue().set("user", s); Object user1 = redisTemplate.opsForValue().get("user"); System.out.println(user1); }
因此,直接创建对象的时候序列号,就不会报错
@Component//方便直接调用@Data@AllArgsConstructor@NoArgsConstructorpublic class User implements Serializable { private String name;private Integer age;}
@Testvoid Test() throws JsonProcessingException { User user = new User("哈哈", 10);// String s = new ObjectMapper().writeValueAsString(user);//不序列号不行,所有可以在pojo里面对象直接序列号redisTemplate.opsForValue().set("user", user);Object user1 = redisTemplate.opsForValue().get("user");System.out.println(user1);}
@Configurationpublic class RedisConfig {
@Bean @SuppressWarnings("all") public RedisTemplate redisTemplate(RedisConnectionFactory factory) {
RedisTemplate template = new RedisTemplate(); template.setConnectionFactory(factory); Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); ObjectMapper om = new ObjectMapper(); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); jackson2JsonRedisSerializer.setObjectMapper(om); StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); // key采用String的序列化方式 template.setKeySerializer(stringRedisSerializer); // hash的key也采用String的序列化方式 template.setHashKeySerializer(stringRedisSerializer); // value序列化方式采用jackson template.setValueSerializer(jackson2JsonRedisSerializer); // hash的value序列化方式采用jackson template.setHashValueSerializer(jackson2JsonRedisSerializer); template.afterPropertiesSet(); return template; }}
import org.springframework.beans.factory.annotation.Autowired;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.stereotype.Component;import org.springframework.util.CollectionUtils; import java.util.List;import java.util.Map;import java.util.Set;import java.util.concurrent.TimeUnit; /** * Redis工具类 * * @author zhangzhixiang * @date 2019年06月19日 */@Componentpublic final class RedisUtil {
@Autowired private RedisTemplate redisTemplate; // =============================common============================ /** * 指定缓存失效时间 * * @param key 键 * @param time 时间(秒) * @return */ public boolean expire(String key, long time) {
try {
if (time > 0) {
redisTemplate.expire(key, time, TimeUnit.SECONDS); } return true; } catch (Exception e) {
e.printStackTrace(); return false; } } /** * 根据key 获取过期时间 * * @param key 键 不能为null * @return 时间(秒) 返回0代表为永久有效 */ public long getExpire(String key) {
return redisTemplate.getExpire(key, TimeUnit.SECONDS); } /** * 判断key是否存在 * * @param key 键 * @return true 存在 false不存在 */ public boolean hasKey(String key) {
try {
return redisTemplate.hasKey(key); } catch (Exception e) {
e.printStackTrace(); return false; } } /** * 删除缓存 * * @param key 可以传一个值 或多个 */ @SuppressWarnings("unchecked") public void del(String... key) {
if (key != null && key.length > 0) {
if (key.length == 1) {
redisTemplate.delete(key[0]); } else {
redisTemplate.delete(CollectionUtils.arrayToList(key)); } } } // ============================String============================= /** * 普通缓存获取 * * @param key 键 * @return 值 */ public Object get(String key) {
return key == null ? null : redisTemplate.opsForValue().get(key); } /** * 普通缓存放入 * * @param key 键 * @param value 值 * @return true成功 false失败 */ public boolean set(String key, Object value) {
try {
redisTemplate.opsForValue().set(key, value); return true; } catch (Exception e) {
e.printStackTrace(); return false; } } /** * 普通缓存放入并设置时间 * * @param key 键 * @param value 值 * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 * @return true成功 false 失败 */ public boolean set(String key, Object value, long time) {
try {
if (time > 0) {
redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); } else {
set(key, value); } return true; } catch (Exception e) {
e.printStackTrace(); return false; } } /** * 递增 * * @param key 键 * @param delta 要增加几(大于0) * @return */ public long incr(String key, long delta) {
if (delta < 0) {
throw new RuntimeException("递增因子必须大于0"); } return redisTemplate.opsForValue().increment(key, delta); } /** * 递减 * * @param key 键 * @param delta 要减少几(小于0) * @return */ public long decr(String key, long delta) {
if (delta < 0) {
throw new RuntimeException("递减因子必须大于0"); } return redisTemplate.opsForValue().increment(key, -delta); } // ================================Map================================= /** * HashGet * * @param key 键 不能为null * @param item 项 不能为null * @return 值 */ public Object hget(String key, String item) {
return redisTemplate.opsForHash().get(key, item); } /** * 获取hashKey对应的所有键值 * * @param key 键 * @return 对应的多个键值 */ public Map hmget(String key) {
return redisTemplate.opsForHash().entries(key); } /** * HashSet * * @param key 键 * @param map 对应多个键值 * @return true 成功 false 失败 */ public boolean hmset(String key, Map map) {
try {
redisTemplate.opsForHash().putAll(key, map); return true; } catch (Exception e) {
e.printStackTrace(); return false; } } /** * HashSet 并设置时间 * * @param key 键 * @param map 对应多个键值 * @param time 时间(秒) * @return true成功 false失败 */ public boolean hmset(String key, Map map, long time) {
try {
redisTemplate.opsForHash().putAll(key, map); if (time > 0) {
expire(key, time); } return true; } catch (Exception e) {
e.printStackTrace(); return false; } } /** * 向一张hash表中放入数据,如果不存在将创建 * * @param key 键 * @param item 项 * @param value 值 * @return true 成功 false失败 */ public boolean hset(String key, String item, Object value) {
try {
redisTemplate.opsForHash().put(key, item, value); return true; } catch (Exception e) {
e.printStackTrace(); return false; } } /** * 向一张hash表中放入数据,如果不存在将创建 * * @param key 键 * @param item 项 * @param value 值 * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 * @return true 成功 false失败 */ public boolean hset(String key, String item, Object value, long time) {
try {
redisTemplate.opsForHash().put(key, item, value); if (time > 0) {
expire(key, time); } return true; } catch (Exception e) {
e.printStackTrace(); return false; } } /** * 删除hash表中的值 * * @param key 键 不能为null * @param item 项 可以使多个 不能为null */ public void hdel(String key, Object... item) {
redisTemplate.opsForHash().delete(key, item); } /** * 判断hash表中是否有该项的值 * * @param key 键 不能为null * @param item 项 不能为null * @return true 存在 false不存在 */ public boolean hHasKey(String key, String item) {
return redisTemplate.opsForHash().hasKey(key, item); } /** * hash递增 如果不存在,就会创建一个 并把新增后的值返回 * * @param key 键 * @param item 项 * @param by 要增加几(大于0) * @return */ public double hincr(String key, String item, double by) {
return redisTemplate.opsForHash().increment(key, item, by); } /** * hash递减 * * @param key 键 * @param item 项 * @param by 要减少记(小于0) * @return */ public double hdecr(String key, String item, double by) {
return redisTemplate.opsForHash().increment(key, item, -by); } // ============================set============================= /** * 根据key获取Set中的所有值 * * @param key 键 * @return */ public Set sGet(String key) {
try {
return redisTemplate.opsForSet().members(key); } catch (Exception e) {
e.printStackTrace(); return null; } } /** * 根据value从一个set中查询,是否存在 * * @param key 键 * @param value 值 * @return true 存在 false不存在 */ public boolean sHasKey(String key, Object value) {
try {
return redisTemplate.opsForSet().isMember(key, value); } catch (Exception e) {
e.printStackTrace(); return false; } } /** * 将数据放入set缓存 * * @param key 键 * @param values 值 可以是多个 * @return 成功个数 */ public long sSet(String key, Object... values) {
try {
return redisTemplate.opsForSet().add(key, values); } catch (Exception e) {
e.printStackTrace(); return 0; } } /** * 将set数据放入缓存 * * @param key 键 * @param time 时间(秒) * @param values 值 可以是多个 * @return 成功个数 */ public long sSetAndTime(String key, long time, Object... values) {
try {
Long count = redisTemplate.opsForSet().add(key, values); if (time > 0) expire(key, time); return count; } catch (Exception e) {
e.printStackTrace(); return 0; } } /** * 获取set缓存的长度 * * @param key 键 * @return */ public long sGetSetSize(String key) {
try {
return redisTemplate.opsForSet().size(key); } catch (Exception e) {
e.printStackTrace(); return 0; } } /** * 移除值为value的 * * @param key 键 * @param values 值 可以是多个 * @return 移除的个数 */ public long setRemove(String key, Object... values) {
try {
Long count = redisTemplate.opsForSet().remove(key, values); return count; } catch (Exception e) {
e.printStackTrace(); return 0; } } // ===============================list================================= /** * 获取list缓存的内容 * * @param key 键 * @param start 开始 * @param end 结束 0 到 -1代表所有值 * @return */ public List lGet(String key, long start, long end) {
try {
return redisTemplate.opsForList().range(key, start, end); } catch (Exception e) {
e.printStackTrace(); return null; } } /** * 获取list缓存的长度 * * @param key 键 * @return */ public long lGetListSize(String key) {
try {
return redisTemplate.opsForList().size(key); } catch (Exception e) {
e.printStackTrace(); return 0; } } /** * 通过索引 获取list中的值 * * @param key 键 * @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推 * @return */ public Object lGetIndex(String key, long index) {
try {
return redisTemplate.opsForList().index(key, index); } catch (Exception e) {
e.printStackTrace(); return null; } } /** * 将list放入缓存 * * @param key 键 * @param value 值 * @return */ public boolean lSet(String key, Object value) {
try {
redisTemplate.opsForList().rightPush(key, value); return true; } catch (Exception e) {
e.printStackTrace(); return false; } } /** * 将list放入缓存 * * @param key 键 * @param value 值 * @param time 时间(秒) * @return */ public boolean lSet(String key, Object value, long time) {
try {
redisTemplate.opsForList().rightPush(key, value); if (time > 0) expire(key, time); return true; } catch (Exception e) {
e.printStackTrace(); return false; } } /** * 将list放入缓存 * * @param key 键 * @param value 值 * @return */ public boolean lSet(String key, List value) {
try {
redisTemplate.opsForList().rightPushAll(key, value); return true; } catch (Exception e) {
e.printStackTrace(); return false; } } /** * 将list放入缓存 * * @param key 键 * @param value 值 * @param time 时间(秒) * @return */ public boolean lSet(String key, List value, long time) {
try {
redisTemplate.opsForList().rightPushAll(key, value); if (time > 0) expire(key, time); return true; } catch (Exception e) {
e.printStackTrace(); return false; } } /** * 根据索引修改list中的某条数据 * * @param key 键 * @param index 索引 * @param value 值 * @return */ public boolean lUpdateIndex(String key, long index, Object value) {
try {
redisTemplate.opsForList().set(key, index, value); return true; } catch (Exception e) {
e.printStackTrace(); return false; } } /** * 移除N个值为value * * @param key 键 * @param count 移除多少个 * @param value 值 * @return 移除的个数 */ public long lRemove(String key, long count, Object value) {
try {
Long remove = redisTemplate.opsForList().remove(key, count, value); return remove; } catch (Exception e) {
e.printStackTrace(); return 0; } }}
@SpringBootTestclass DemoApplicationTests {
@Autowired private RedisUtil redisUtil; @Test void contextLoads() {
} @Test void Test() throws JsonProcessingException {
User user = new User("哈哈", 10); redisUtil.set("user1", user); Object user1 = redisUtil.get("user1"); System.out.println(user1); } }
locate redis.confcd ..到目录vim redis.conf
bind 127.0.0.1protected-mode yesport 6379daemonize yes #守护进程方式运行,如果是no需改为yesloglevel notice #日志logfile "/www/server/redis/redis.log"databases 16 #默认16个数据库always-show-logo yes #显示logo# save "" 持久化规则save 900 1 #900内,有一个key进行修改,进行持久化save 300 10 #300秒内,10个key进行修改就持久化save 60 10000 #60秒内10000次修改则持久化stop-writes-on-bgsave-error yes #持久化错误后默认继续工作rdbcompression yes #是否压缩rdbchecksum yes #保存rdb时候进行校验dbfilename dump.rdbdir /www/server/redis/ #rdb保存文件目录################ REPLICATION ####################主从复制########## SECURITY #############可以设置密码config get requirepass 获取密码>requirepass 123456 #如果在### SECURITY #####加上这句,就会设置密码或者直接命令设置:config set requirepass "123456"这样下次需要先`auth 123456` 才可以继续操作############## CLIENTS ################## maxclients 10000 #最大客户数# maxmemory-policy noeviction #内存策略
################ APPEND ONLY MODE #############AOF配置appendonly no #默认不开启,默认rdb持久化,大部分时间够用了appendfilename "appendonly.aof" #持久化文件名字save 保存配置文件设置
RDB==> dump.rdb
locate dump.rdb 定位dump.rdb
执行flushall,退出redis都会产生rdb文件
如果需要恢复rdb,则定位dir,后续待补充
127.0.0.1:6379> config get dir1) "dir"2) "/www/server/redis"
AOF如果有错位,redis无法启动,需要修复这个文件
redis-check-aof --fix appendonly.aof
subscribe channel #订阅频道publish channel "hello" #发送消息到频道
主从复制,读写分离,主写从读
一主二从,集群至少需要三台服务器
默认都是主,变成从需要配置
info replication
查看信息
如何设置为从机
slaveof 127.0.0.1 6379
即slaveof ip port
认主机为老大
masterauth password
验证主机密码
slave no one
自己当主机,手动的
如何解决主从设置失败
redis问题解决:Error condition on socket for SYNC: No route to host第一种方案:1.telnet ip port 是否通2.使用netstat -tnlp 查询IP地址是否为0.0.0.0(127.0.0.1代表只能本机使用)3.修改master中redis.conf中bind绑定0.0.0.02.重启master服务如果第一种方案行不通,那就使用第二种方案;第二种方案:1.关闭防火墙:service iptables stop2.如果出现以下异常Redirecting to /bin/systemctl stop iptables.serviceFailed to stop iptables.service: Unit iptables.service not loaded.(其他异常也可以试下)3.进入/etc/sysconfig/目录下查询有没有iptables文件4.如果没有,使用systemctl stop firewalld 关闭防火墙5.使用yum install iptables-services 安装或者更新服务6.service iptables stop尝试下关闭服务器7.关闭成功无异常,重启maste和slave,进入redis-cli 输入info就能看到maste和slave信息了
出现了哨兵模式.就自动了
(自动选举主机)
真正实施需要六个进程:三个哨兵互相监督.
# 禁止保护模式protected-mode no# 配置监听的主服务器,这里sentinel monitor代表监控,mymaster代表服务器的名称,可以自定义,192.168.11.128代表监控的主服务器,6379代表端口,1代表只有两个或两个以上的哨兵认为主服务器不可用的时候,才会进行failover操作。sentinel monitor mymaster 192.168.81.83 6379 1# sentinel author-pass定义服务的密码,mymaster是服务名称,123456是Redis服务器密码# sentinel auth-pass sentinel auth-pass mymaster 123456
启动哨兵模式:与启动redis类似
/www/server/redis/src/redis-sentinel /www/server/redis/sentinel.conf