# Nicksxs's Blog

What hurts more, the pain of hard work or the pain of regret?

0%

## 聊聊 Sharding-Jdbc 的简单使用

发表于 2021-12-12 分类于 Java 阅读次数： Disqus：

我们在日常工作中还是使用比较多的分库分表组件的，其中比较优秀的就有 Sharding-Jdbc，一开始由当当开源，后来捐献给了 Apache，说一下简单使用，因为原来经常的使用都是基于 xml 跟 properties 组合起来使用，这里主要试下用 Java Config 来配置
首先是通过 Spring Initializr 创建个带 jdbc 的 Spring Boot 项目，然后引入主要的依赖

    <dependency>
        <groupId>org.apache.shardingsphere</groupId>
        <artifactId>shardingsphere-jdbc-core</artifactId>
        <version>5.0.0-beta</version>
    </dependency>

因为前面有聊过 Spring Boot 的自动加载，在这里 spring 就会自己去找 DataSource 的配置，所以要在入口把它干掉

    @SpringBootApplication(exclude = { DataSourceAutoConfiguration.class})
    public class ShardingJdbcDemoApplication implements CommandLineRunner {

然后因为想在入口跑代码，就实现了下 `org.springframework.boot.CommandLineRunner` 主要是后面的 Java Config 代码

    // 注意这里的注解，可以让 Spring 自动帮忙加载，也就是 Java Config 的核心
    @Configuration
    public class MysqlConfig {

        @Bean
        public DataSource dataSource() throws SQLException {
            // Configure actual data sources
            Map<String, DataSource> dataSourceMap = new HashMap<>();

            // Configure the first data source
            // 使用了默认的Hikari连接池的 DataSource
            HikariDataSource dataSource1 = new HikariDataSource();
            dataSource1.setDriverClassName("com.mysql.jdbc.Driver");
            dataSource1.setJdbcUrl("jdbc:mysql://localhost:3306/sharding");
            dataSource1.setUsername("username");
            dataSource1.setPassword("password");
            dataSourceMap.put("ds0", dataSource1);

            // Configure student table rule
            // 这里是配置分表逻辑，逻辑表是 student，对应真实的表是 student_0 到 student_1, 这个配置方式就是有多少表可以用 student_$->{0..n}
            ShardingTableRuleConfiguration studentTableRuleConfig = new ShardingTableRuleConfiguration("student", "ds0.student_$->{0..1}");

            // 设置分表字段
            studentTableRuleConfig.setTableShardingStrategy(new StandardShardingStrategyConfiguration("user_id", "tableShardingAlgorithm"));

            // Configure sharding rule
            // 配置 studentTableRuleConfig
            ShardingRuleConfiguration shardingRuleConfig = new ShardingRuleConfiguration();
            shardingRuleConfig.getTables().add(studentTableRuleConfig);

            // Configure table sharding algorithm
            Properties tableShardingAlgorithmrProps = new Properties();
            // 算法表达式就是根据 user_id 对 2 进行取模
            tableShardingAlgorithmrProps.setProperty("algorithm-expression", "student_${user_id % 2}");
            shardingRuleConfig.getShardingAlgorithms().put("tableShardingAlgorithm", new ShardingSphereAlgorithmConfiguration("INLINE", tableShardingAlgorithmrProps));

            // 然后创建这个 DataSource
            return ShardingSphereDataSourceFactory.createDataSource(dataSourceMap, Collections.singleton(shardingRuleConfig), new Properties());

        }
    }

然后我们就可以在使用这个 DataSource 了，先看下这两个表的数据

    @Override
        public void run(String... args) {
            LOGGER.info("run here");
            String sql = "SELECT * FROM student WHERE user_id=? ";
            try (
                    Connection conn = dataSource.getConnection();
                    PreparedStatement ps = conn.prepareStatement(sql)) {
                // 参数就是 user_id，然后也是分表键，对 2 取模就是 1，应该是去 student_1 取数据
                ps.setInt(1, 1001);

                ResultSet resultSet = ps.executeQuery();
                while (resultSet.next()) {
                    final int id = resultSet.getInt("id");
                    final String name = resultSet.getString("name");
                    final int userId = resultSet.getInt("user_id");
                    final int age = resultSet.getInt("age");
                    System.out.println("奇数表 id：" + id + " 姓名：" + name
                            + " 用户 id：" + userId + " 年龄：" + age );
                    System.out.println("=============================");
                }
                // 参数就是 user_id，然后也是分表键，对 2 取模就是 0，应该是去 student_0 取数据
                ps.setInt(1, 1000);
                resultSet = ps.executeQuery();
                while (resultSet.next()) {
                    final int id = resultSet.getInt("id");
                    final String name = resultSet.getString("name");
                    final int userId = resultSet.getInt("user_id");
                    final int age = resultSet.getInt("age");
                    System.out.println("偶数表 id：" + id + " 姓名：" + name
                            + " 用户 id：" + userId + " 年龄：" + age );
                    System.out.println("=============================");
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

看下查询结果

## 聊聊部分公交车的设计bug

发表于 2021-12-05 分类于 生活 阅读次数： Disqus：

今天惯例坐公交回住的地方，不小心撞了头，原因是我们想坐倒数第二排，然后LD 走在我后面，我就走到最后一排中间等着，但是最后一排是高一截的，等 LD 坐进去以后，我就往前走，结果撞到了车顶的扶手杆子的一端，差点撞昏了去，这里我觉得其实杆子长度应该短一点，不然从最后一排出来，还是有比较大概率因为没注意看而撞到头，特别是没注意看的情况，发力其实会比较大，一头撞上就会像我这样，眼前一黑，又痛得要死。
还有一点就是座位设计了，先来看个图
图里大致画了两条线，因为可能是轮胎还是什么原因，后排中间会有那么大的突起，但是看两条红线可以发现，靠近过道的座位边缘跟地面突起的边缘不是一样宽的，这样导致的结果就是坐着的时候有一个脚没地儿搁，要不就得侧着斜着坐，或者就是一个脚悬空，短程的可能还好，路程远一点还是比较难受的，特别是像我现在这样，大腿外侧有点难受的情况，就会更难受。
虽然说这两个点，基本是屁用没有，但是我也是在自己这个博客说说，也当是个树洞了。

## wordpress 忘记密码的一种解决方法

发表于 2021-12-05 分类于 小技巧 阅读次数： Disqus：

前阵子搭了个 WordPress，但是没怎么用，前两天发现忘了登录密码了，最近不知道是什么情况，chrome 的记住密码跟历史记录感觉有点问题，历史记录丢了不少东西，可能是时间太久了，但是理论上应该有 LRU 这种策略的，有些还比较常用，还有记住密码，因为个人域名都是用子域名分配给各个服务，有些记住了，有些又没记住密码，略蛋疼，所以就找了下这个方案。
当然这个方案不是最优的，有很多限制，首先就是要能够登陆 WordPress 的数据库，不然这个方法是没用的。
首先不管用什么方式（别违法）先登陆数据库，选择 WordPress 的数据库，可以看到里面有几个表，我们的目标就是 `wp_users` 表，用 `select` 查询看下可以看到有用户的数据，如果是像我这样搭着玩的没有创建其他用户的话应该就只有一个用户，那我们的表里的用户数据就只会有一条，当然多条的话可以通过用户名来找
然后可能我这个版本是这样，没有装额外的插件，密码只是经过了 MD5 的单向哈希，所以我们可以设定一个新密码，然后用 MD5 编码后直接更新进去

    UPDATE wp_users SET user_pass = MD5('123456') WHERE ID = 1;

然后就能用自己的账户跟刚才更新的密码登录了。

## Leetcode 053 最大子序和 ( Maximum Subarray ) 题解分析

发表于 2021-11-28 分类于 Java ， leetcode 阅读次数： Disqus：

### 题目介绍

Given an integer array `nums`, find the contiguous subarray (containing at least one number) which has the largest sum and return its sum.

A subarray is a contiguous part of an array.

#### 示例

Example 1:

> Input: nums = [-2,1,-3,4,-1,2,1,-5,4]
> Output: 6
> Explanation: [4,-1,2,1] has the largest sum = 6.

Example 2:

> Input: nums = [1]
> Output: 1

Example 3:

> Input: nums = [5,4,-1,7,8]
> Output: 23

说起来这个题其实非常有渊源，大学数据结构的第一个题就是这个，而最佳的算法就是传说中的 online 算法，就是遍历一次就完了，最基本的做法就是记下来所有的连续子数组，然后求出最大的那个。

### 代码

    public int maxSubArray(int[] nums) {
            int max = nums[0];
            int sum = nums[0];
            for (int i = 1; i < nums.length; i++) {
                // 这里最重要的就是这一行了，其实就是如果前面的 sum 是小于 0 的，那么就不需要前面的 sum，反正加上了还不如不加大
                sum = Math.max(nums[i], sum + nums[i]);
                // max 是用来承载最大值的
                max = Math.max(max, sum);
            }
            return max;
        }

## 聊聊最近平淡的生活之看看老剧

发表于 2021-11-21 分类于 生活 阅读次数： Disqus：

最近因为也没什么好看的新剧和综艺所以就看看一些以前看过的老剧，我是个非常念旧的人吧，很多剧都会反反复复地看，一方面之前看过觉得好看的的确是一直记着，还有就是平时工作完了回来就想能放松下，剧情太纠结的，太烧脑的都不喜欢，也就是我常挂在口头的不喜欢看费脑子的剧，跟我不喜欢狼人杀的原因也类似。

前面其实是看的太阳的后裔，跟 LD 一起看的，之前其实算是看过一点，但是没有看的很完整，并且很多剧情也忘了，只是这个我我可能看得更少一点，因为最开始的时候觉得男主应该是男二，可能对长得这样的男主并且是这样的人设有点失望，感觉不是特别像个特种兵，但是由于本来也比较火，而且 LD 比较喜欢就从这个开始看了，有两个点是比较想说的

韩剧虽然被吐槽的很多，但是很多剧的质量，情节把控还是优于目前非常多国内剧的，相对来说剧情发展的前后承接不是那么硬凹出来的，而且人设都立得住，这个是非常重要的，很多国内剧怎么说呢，就是当爹的看起来就比儿子没大几岁，三四十岁的人去演一个十岁出头的小姑娘，除非容貌异常，比如刘晓庆这种，不然就会觉得导演在把我们观众当傻子。瞬间就没有想看下去的欲望了。

再一点就是情节是大众都能接受度比较高的，现在有很多普遍会找一些新奇的视角，比如卖腐，想某某令，两部都叫某某令，这其实是一个点，延伸出去就是跟前面说的一点有点类似，xx 老祖，人看着就二三十，叫 xx 老祖，（喜欢的人轻喷哈）然后名字有一堆，同一个人物一会叫这个名字，一会又叫另一个名字，然后一堆死表情。

因为今天有个特殊的事情发生，所以简短的写（shui）一篇了