爱看书的阿东

赐他一块白色石头,石头上写着新名

Redis学习 - 复制以及三种部署模式

什么是复制

单机的redis通常情况是无法满足项目需求的,一般都建议使用集群部署的方式进行数据的多机备份和部署,这样既可以保证数据安全,同时在redis宕机的时候,复制也可以对于数据进行快速的修复。

阅读全文 »

【Maven】Maven 多模块和依赖冲突问题汇总记录

目录

[TOC]

前言:

今天学习和总结了一下maven的相关知识点,发现一些比较基础的东西居然也会忘记,这里对于一些日常工作中可能会遇到的问题进行了一下汇总。

idea怎么创建maven多module的项目

首先了解上面是多module?

一句话概括就是:一个父模块作为版本控制多个子模块,子模块负责接入到父模块当中作为整个项目的过程。

多Module管理项目的几种方式:

  1. 按照单模块拆分为多个子模块,比如将MVC三层架构拆分为 xxx-service,xxx-dao,xxx-model,不过这种方式个人感觉比较二,目前以业务模块拆分比较多,迁移到微服务比如用springcloude或者dubbo 的时候非常好用。
  2. 按照业务模块拆分,这种模式使用的比较多,也比较多见。
阅读全文 »

消息通信模式,发送者发送消息,接受者接受消息,微信,微博,关注系统

redis客户端可以订阅任意数量的频道

订阅/发布消息:

  1. 消息发送者
  2. 频道
  3. 消息内容
  4. 消息接受者
阅读全文 »

无论面试和工作,持久化都是重点。

一般情况下,redis占用内存超过20GB以上的时候,必须考虑主从多redis实例进行数据同步和备份保证可用性。

rbd保存的文件都是 dump.rdb,都是配置文件当中的快照配置进行生成的。一般业务情况只需要用rdb即可。

aof默认是不开启的,因为aof非常容易产生大文件,虽然官方提供重写但是在文件体积过大的时候还是容易造成阻塞,谨慎考虑使用

rbd和aof在大数据量分别有各种不同情况的系统性能影响,具体使用何种解决策略需要根据系统资源以及业务的实际情况决定。

阅读全文 »

下载mysql源安装包

1
wget http://dev.mysql.com/get/mysql57-community-release-el7-8.noarch.rpm

安装mysql源

1
yum localinstall mysql57-community-release-el7-8.noarch.rpm

检测是否安装完成

1
yum repolist enabled | grep "mysql.*-community.*"

安装mysql

1
yum install mysql-community-server

设置开启启动mysql服务

1
systemctl enable mysqld

查看安装的mysql版本

1
rpm -aq | grep -i mysql

启动MySQL服务

1
systemctl restart mysqld

查看MySQL初始密码

1
grep 'A temporary password' /var/log/mysqld.log

执行上面步骤可以获得mysql初始数据库密码:

1
获取到初始密码:.DhtciCJ?3rg

根据此密码就可以在第一次root登录的时候修改密码

更改MySQL密码

mysqladmin -u root -p'旧密码' password '新密码'

初始化更改密码的案例

1
mysqladmin  -u root -p 'xxx' password 'xxxxx'
1
alter user 'root'@'localhost' identified by '.DhtciCJ?3rg' # 这里用刚刚到随机初始密码

这里会可能出现更改失败的问题

方法一:把密码设置复杂点(这是最直接的方法)

方法二:关闭mysql密码强度验证(validate_password)

    编辑配置文件:vim /etc/my.cnf, 增加这么一行validate_password=off

    编辑后重启mysql服务:systemctl restart mysqld

设置mysql能够远程访问(不建议使用root)

1. 登录进MySQL:mysql -uroot -p密码

注意只有root用户才可以操作

2. 在阿里云当中增加一个用户给予访问权限:

具体查看阿里云配置安全组

开放用户远程访问:

https://www.cnblogs.com/hoge/p/4958214.html

mysql中添加一个和root一样的用户用于远程连接:

大家在拿站时应该碰到过。root用户的mysql,只可以本地连,对外拒绝连接。

下面语句添加一个新用户administrtor

1
2
3
4
5
-- 创建新用户
CREATE USER 'monitor'@'%' IDENTIFIED BY 'admin';

-- 给用户分配root并且支持远程访问
GRANT ALL PRIVILEGES ON *.* TO 'monitor'@'%' IDENTIFIED BY 'admin' WITH GRANT OPTION MAX_QUERIES_PER_HOUR 0 MAX_CONNECTIONS_PER_HOUR 0 MAX_UPDATES_PER_HOUR 0 MAX_USER_CONNECTIONS 0;

删除这个用户:

1
2
3
4
-- 删除用户
DROP USER 'monitor'@'%';
-- 删除具体分配表
DROP DATABASE IF EXISTS `monitor` ;

3. 阿里云的安全组设置里面选择添加安全组规则,开启3306端口。授权对象选择0.0.0.0/0所有ip可访问,如果添加限制可以点击旁面的小叹号。

4. 最后:建议重启一下mysqld的服务

前言:

导出word的需求其实在日常工作中用到的地方还不少,于是想写一篇文章好好记录一下,在导出之前,需要了解一下关于浏览器如何处理servlet的后台数据。具体可以了解一下http通信下载行为在servlet的实现。

==导出的工具类代码来源于网络,如有侵权可以联系我删除文章==

个人使用==ftl==作为word导出模板引擎,有很多模板引擎可以选,个人经过查阅资料发现ftl用的比较多,所以选择这一种

阅读全文 »

我的Neo4j探索之旅 - 初识Neo4j(一)

目录

[TOC]

前言:

neo4j 这个东西在国内用的很少,目前能百度的资料也是很早之前的几篇了,我针对neo4j 3.5 的版本进行一次学习和记录,以及实际的工作需求我也遇到了,后续会开源一个剔除业务的开源项目,有兴趣的读者可以了解一下图数据库的中间件,还是蛮有意思的。

阅读全文 »

一次短信验证码整改实验

前言:

讨论内容部分为当初的一些短信验证码的需求细节讨论

这个短信验证码在并发量非常大的情况下有可能会失效,后续会进行整改升级,保证线程安全

阅读全文 »

前言

从github上面摘录的一个雪花算法的实现,可以作为学习参考

具体代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
package com.myapp.cunpleuserapp.util;

/**
* Twitter_Snowflake<br>
* SnowFlake的结构如下(每部分用-分开):<br>
* 0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000 <br>
* 1位标识,由于long基本类型在Java中是带符号的,最高位是符号位,正数是0,负数是1,所以id一般是正数,最高位是0<br>
* 41位时间截(毫秒级),注意,41位时间截不是存储当前时间的时间截,而是存储时间截的差值(当前时间截 - 开始时间截)
* 得到的值),这里的的开始时间截,一般是我们的id生成器开始使用的时间,由我们程序来指定的(如下下面程序IdWorker类的startTime属性)。41位的时间截,可以使用69年,年T = (1L << 41) / (1000L * 60 * 60 * 24 * 365) = 69<br>
* 10位的数据机器位,可以部署在1024个节点,包括5位datacenterId和5位workerId<br>
* 12位序列,毫秒内的计数,12位的计数顺序号支持每个节点每毫秒(同一机器,同一时间截)产生4096个ID序号<br>
* 加起来刚好64位,为一个Long型。<br>
* SnowFlake的优点是,整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞(由数据中心ID和机器ID作区分),并且效率较高,经测试,SnowFlake每秒能够产生26万ID左右。
*/
public class SnowflakeIdWorker {

// ==============================Fields===========================================
/** 开始时间截 (2015-01-01) */
private final long twepoch = 1420041600000L;

/** 机器id所占的位数 */
private final long workerIdBits = 5L;

/** 数据标识id所占的位数 */
private final long datacenterIdBits = 5L;

/** 支持的最大机器id,结果是31 (这个移位算法可以很快的计算出几位二进制数所能表示的最大十进制数) */
private final long maxWorkerId = -1L ^ (-1L << workerIdBits);

/** 支持的最大数据标识id,结果是31 */
private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);

/** 序列在id中占的位数 */
private final long sequenceBits = 12L;

/** 机器ID向左移12位 */
private final long workerIdShift = sequenceBits;

/** 数据标识id向左移17位(12+5) */
private final long datacenterIdShift = sequenceBits + workerIdBits;

/** 时间截向左移22位(5+5+12) */
private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;

/** 生成序列的掩码,这里为4095 (0b111111111111=0xfff=4095) */
private final long sequenceMask = -1L ^ (-1L << sequenceBits);

/** 工作机器ID(0~31) */
private long workerId;

/** 数据中心ID(0~31) */
private long datacenterId;

/** 毫秒内序列(0~4095) */
private long sequence = 0L;

/** 上次生成ID的时间截 */
private long lastTimestamp = -1L;

//==============================Constructors=====================================
/**
* 构造函数
* @param workerId 工作ID (0~31)
* @param datacenterId 数据中心ID (0~31)
*/
public SnowflakeIdWorker(long workerId, long datacenterId) {
if (workerId > maxWorkerId || workerId < 0) {
throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
}
if (datacenterId > maxDatacenterId || datacenterId < 0) {
throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));
}
this.workerId = workerId;
this.datacenterId = datacenterId;
}

// ==============================Methods==========================================
/**
* 获得下一个ID (该方法是线程安全的)
* @return SnowflakeId
*/
public synchronized long nextId() {
long timestamp = timeGen();

//如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退过这个时候应当抛出异常
if (timestamp < lastTimestamp) {
throw new RuntimeException(
String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
}

//如果是同一时间生成的,则进行毫秒内序列
if (lastTimestamp == timestamp) {
sequence = (sequence + 1) & sequenceMask;
//毫秒内序列溢出
if (sequence == 0) {
//阻塞到下一个毫秒,获得新的时间戳
timestamp = tilNextMillis(lastTimestamp);
}
}
//时间戳改变,毫秒内序列重置
else {
sequence = 0L;
}

//上次生成ID的时间截
lastTimestamp = timestamp;

//移位并通过或运算拼到一起组成64位的ID
return ((timestamp - twepoch) << timestampLeftShift) //
| (datacenterId << datacenterIdShift) //
| (workerId << workerIdShift) //
| sequence;
}

/**
* 阻塞到下一个毫秒,直到获得新的时间戳
* @param lastTimestamp 上次生成ID的时间截
* @return 当前时间戳
*/
protected long tilNextMillis(long lastTimestamp) {
long timestamp = timeGen();
while (timestamp <= lastTimestamp) {
timestamp = timeGen();
}
return timestamp;
}

/**
* 返回以毫秒为单位的当前时间
* @return 当前时间(毫秒)
*/
protected long timeGen() {
return System.currentTimeMillis();
}

//==============================Test=============================================
/** 测试 */
public static void main(String[] args) {
SnowflakeIdWorker idWorker = new SnowflakeIdWorker(0, 0);
for (int i = 0; i < 1000; i++) {
long id = idWorker.nextId();
System.out.println(Long.toBinaryString(id));
System.out.println(id);
}
}
}